POJ 1661 DP

中问题不再解释

dp[i][0]表示下落到第i个平台的最左端需要的最少时间

dp[i][1]表示下落到第i个平台的最右端需要的最少时间

把起始点和地面也作为一个平面

#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
const int inf=0x3f3f3f3f;
struct Mark
{
    int l,r,h;
}mark[1010];

bool cmp(Mark a,Mark b)
{
    return a.h>b.h;
}

int Min(int a,int b)
{
    if (a<b) return a;
    else return b;
}
int main()
{
    int T,n,i,j,flag1,flag2,ans,maxy;
    int dp[1010][2];
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d%d%d",&n,&mark[0].l,&mark[0].h,&maxy);
        ans=inf;
        mark[0].r=mark[0].l;

        memset(dp,inf,sizeof(dp));
        for (i=1;i<=n;i++)
            scanf("%d%d%d",&mark[i].l,&mark[i].r,&mark[i].h);
        sort(mark,mark+n+1,cmp);
        mark[n+1].l=-20000;
        mark[n+1].r=20000;
        mark[n+1].h=0;
        dp[0][0]=dp[0][1]=0;

        for (i=0;i<=n;i++)
        {
            flag1=flag2=0;
            for (j=i+1;j<=n+1;j++)
            {
                if (flag1+flag2==2 || mark[i].h-mark[j].h>maxy) break;

                if (flag1==0 && mark[i].l>=mark[j].l && mark[i].l<=mark[j].r && mark[i].h!=mark[j].h)// 从i平台的左端掉落到j平台
                {
                    flag1=1;
                    if (j==n+1)
                        ans=Min(ans,dp[i][0]); // 掉落到地面时特殊处理
                    else
                    {
                        dp[j][0]=Min(dp[j][0],dp[i][0]+mark[i].l-mark[j].l); // 到j平面左端
                        dp[j][1]=Min(dp[j][1],dp[i][0]+mark[j].r-mark[i].l); // 到j平面右端
                    }
                }

                if (flag2==0 && mark[i].r>=mark[j].l && mark[i].r<=mark[j].r && mark[i].h!=mark[j].h) //从i平面的右端掉落到j平面
                {
                    flag2=1;
                    if (j==n+1)
                        ans=Min(ans,dp[i][1]);
                    else
                    {
                        dp[j][0]=Min(dp[j][0],dp[i][1]+mark[i].r-mark[j].l);
                        dp[j][1]=Min(dp[j][1],dp[i][1]+mark[j].r-mark[i].r);
                    }
                }
            }
        }
        printf("%d\n",ans+mark[0].h);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值