POJ 1661(中等 dp,跳板游戏)

本文介绍了解决POJ 1661问题的一种动态规划方法,通过将问题分解为从起点到每个平台左端点和右端点的最短时间计算,最终求得到达底部的最短时间。

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

http://poj.org/problem?id=1661

题意:不多讲,求从出发点到底的最短时间。


思路:把从一个点到下一个板的问题看成两个雷同的问题,一切尽在代码解释中。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>

#define M 1000
#define inf 0x3f3f3f3f

using namespace std;

int aLeftMinTime[M+10];     //记录左点到底的最短时间
int aRightMinTime[M+10];    //记录右点到底的最短时间

int n,x,y,Max;

class Platform
{
public:
    int Lx,Rx,h;            //记录端点和高度
}platform[M+10];

int cmp(Platform a,Platform b)  //按高度进行排序
{
    return a.h > b.h;
}

int MinTime(int L,bool bLeft)   //分成两个子问题,从左点和从右点
{                               //bLeft是区别左右
    int y = platform[L].h;
    int x;
    if(bLeft)
        x = platform[L].Lx;
    else
        x = platform[L].Rx;

    int i;
    for(i = L + 1;i <= n; i++)  //找出下面有没有线段可以落地
        if(platform[i].Lx <= x && platform[i].Rx >= x)
            break;
    if(i <= n){                 //如果有则分成两种情况,一是可以跳,二是不可以
        if(y - platform[i].h > Max)
            return inf;
    }
    else {              //如果没有线段则看是否能直接跳到底
        if(y > Max)
            return inf;
        else
            return y;
    }

    int nLeftMinTime = y - platform[i].h + x - platform[i].Lx;  //到下一个线段左点需要的时间
    int nRightMinTime = y - platform[i].h + platform[i].Rx - x; //到下一个线段右点需要的时间

        //这是分成两个子问题,结果是取时间最短的
    if(aLeftMinTime[i] == -1)   //判断是否走过,优化
        aLeftMinTime[i] = MinTime(i,true);
    if(aRightMinTime[i] == -1)
        aRightMinTime[i] = MinTime(i,false);

    nLeftMinTime += aLeftMinTime[i];
    nRightMinTime += aRightMinTime[i];

    if(nLeftMinTime < nRightMinTime)
        return nLeftMinTime;
    return nRightMinTime;
}

int main()
{
   // freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--){

        memset(aLeftMinTime,-1,sizeof(aLeftMinTime));
        memset(aRightMinTime,-1,sizeof(aRightMinTime));
        scanf("%d%d%d%d",&n,&x,&y,&Max);
        platform[0].Lx = x;
        platform[0].Rx = x;
        platform[0].h = y;

        for(int i = 1;i <= n; i++)
            scanf("%d%d%d",&platform[i].Lx,&platform[i].Rx,&platform[i].h);

        sort(platform,platform+n+1,cmp);
        printf("%d\n",MinTime(0,true));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值