【POJ 1661 Help Jimmy】 DP

博客围绕POJ1661题目展开,该题是小人在最高平台选择向左或右走,每秒行走和下降速度为1,有最长下降距离限制。解题思路是设置两个下降状态,按高度从下向上更新,分别设置小人站在i块从左侧和右侧下降到达地面的最短时间状态,具体实现看代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


POJ1661
POJ1661题目链接
题意就是一个小人在最高的平台上选择向左或者向右走,每秒的行走速度和下降速度都是1,有一个最长的下降的距离,超过这个距离就会GG,求最小时间
由于小人只能选择从左侧下降或者从右侧下降,我们只要设置两个下降状态,然后按照高度排序从下向上一下就可以了
设置 dp[0][i]i d p [ 0 ] [ i ] 为 小 人 站 在 i 块 选 择 从 左 侧 下 降 时 的 到 达 地 面 的 最 短 时 间
设置 dp[1][i]i d p [ 1 ] [ i ] 为 小 人 站 在 i 块 选 择 从 右 侧 下 降 时 的 到 达 地 面 的 最 短 时 间
然后从低到高进行更新就可以了。具体实现看代码。
POJ1661代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn = 1005;
const int INF = 0x3f3f3f3f;
struct data
{
    int l,r,h;
}x[maxn];
int dp[2][maxn];
bool cmp(const data &a,const data &b)
{
    if(a.h==b.h) return a.l<=b.l;
    return a.h<b.h;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,X,Y,maxx;
        scanf("%d%d%d%d",&n,&X,&Y,&maxx);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&x[i].l,&x[i].r,&x[i].h);
        }
        for(int i=0;i<=n+1;i++)
        {
            dp[0][i]=INF;
            dp[1][i]=INF;
        }
        sort(x+1,x+1+n,cmp);
        x[n+1].l=X;
        x[n+1].r=X;
        x[n+1].h=Y;
        for(int i=1;i<=n+1;i++)
        {
            for(int j=i-1;j>=1;j--)
            {
                if(x[i].h-x[j].h<=maxx&&x[i].h>x[j].h)
                {
                    if(x[j].l<=x[i].l&&x[i].l<=x[j].r)
                    {
                        dp[0][i]=min(dp[0][i],x[i].h-x[j].h+min(dp[0][j]+x[i].l-x[j].l,dp[1][j]+x[j].r-x[i].l));
                        break;
                    }
                }
            }
            if(dp[0][i]==INF)
            {
                if(x[i].h>maxx) dp[0][i]=INF;
                else dp[0][i]=x[i].h;
            }
            for(int j=i-1;j>=1;j--)
            {
                if(x[i].h-x[j].h<=maxx&&x[i].h>x[j].h)
                {
                    if(x[j].l<=x[i].r&&x[i].r<=x[j].r)
                    {
                        dp[1][i]=min(dp[1][i],x[i].h-x[j].h+min(dp[0][j]+x[i].r-x[j].l,dp[1][j]+x[j].r-x[i].r));
                        break;
                    }
                }
            }
            if(dp[1][i]==INF)
            {
                if(x[i].h>maxx) dp[1][i]=INF;
                else dp[1][i]=x[i].h;
            }
        }
        printf("%d\n",min(dp[0][n+1],dp[1][n+1]));
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值