POJ 1661 Help Jimmy

题目链接:http://poj.org/problem?id=1661

联动:http://blog.csdn.net/csdn364988181/article/details/48208349


题意:场景中有n个平台,角色从某个地方下落,到达地面结束,从一个平台到另一个平台不可以超过max,不然摔死,在平台上移动速度是1m/s,下落的速度也是1m/s,问最快到达地面要多少


思路:立刻想到了之前用线段树处理每一个平台左右落点的题目(联动hdu3016的题解),但是这一题数据比较小,直接暴力判断落点就可以了,递推的方式特有些不一样,但大体上思路是一样的,一个平台只能选择左右2个地方下落,按高度进行排序一直递推上去就可以了,[0,10]的平台是可以从右侧落到[10,100]上的逻辑(一开始我没在意,不过有人写的题解抱怨了这个逻辑)



#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;

struct Node
{
    int xl,xr,h;
}s[1030];

int lim,n;
int dp[1030][5];

bool cmp(Node p,Node q)
{
    return p.h<q.h;
}

void Leftmintime(int now)
{
    int tmp=now-1;
    while (tmp>0 && s[now].h-s[tmp].h <= lim)
    {
        if (s[now].xl >= s[tmp].xl && s[now].xl <= s[tmp].xr)
        {
            int mintim=min(s[now].xl-s[tmp].xl+dp[tmp][0],s[tmp].xr-s[now].xl+dp[tmp][1]);
            dp[now][0]=s[now].h-s[tmp].h+mintim;
            return;
        }
        else tmp--;
    }

    if (s[now].h > lim)
      dp[now][0]=inf;
    else
      dp[now][0]=s[now].h;
    return;
}

void Rightmintime(int now)
{
    int tmp=now-1;
    while (tmp>0 && s[now].h-s[tmp].h <= lim)
    {
        if (s[now].xr >= s[tmp].xl && s[now].xr <= s[tmp].xr)
        {
            int mintim=min(s[now].xr-s[tmp].xl+dp[tmp][0],s[tmp].xr-s[now].xr+dp[tmp][1]);
            dp[now][1]=s[now].h-s[tmp].h+mintim;
            return;
        }
        else tmp--;
    }

    if (s[now].h > lim)
      dp[now][1]=inf;
    else
      dp[now][1]=s[now].h;
    return;
}




int solve()
{
    for (int i=1;i<=n+1;i++)
    {//cout<<":"<<endl;
        Leftmintime(i);
        Rightmintime(i);
    }

    int res=min(dp[n+1][0],dp[n+1][1]);
    return res;
}


int main()
{
    int t,x,y;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d%d%d",&n,&x,&y,&lim);
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&s[i].xl,&s[i].xr,&s[i].h);
        }

        s[0].xl=-inf;
        s[0].xr=inf;
        s[0].h=0;
        s[n+1].xl=x;
        s[n+1].xr=x;
        s[n+1].h=y;
        sort(s,s+n+1,cmp);
        int res=solve();
        printf("%d\n",res);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值