POJ 1661 Help Jimmy

简单DP,每一条线段记录两个值,到左端点最少时间与到又端点最少时间。按照这个往后推导。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn=1000+10;
int T;
int N,X,Y,MAX;
struct W
{
    int x1,x2,h;
} s[maxn];
int dpLeft[maxn],dpRight[maxn];

bool cmp(const W&a,const W&b)
{
    return a.h>b.h;
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&N,&X,&Y,&MAX);
        s[0].x1=X,s[0].x2=X,s[0].h=Y;
        for(int i=1; i<=N; i++) scanf("%d%d%d",&s[i].x1,&s[i].x2,&s[i].h);
        s[N+1].x1=-0x7fffffff,s[N+1].x2=0x7FFFFFFF,s[N+1].h=0;

        for(int i=0; i<=N+1; i++) dpRight[i]=dpLeft[i]=0x7fffffff;
        sort(s+1,s+N+1,cmp);

        dpLeft[0]=0,dpRight[0]=0;
        int ans=0x7FFFFFFF;
        for(int i=0; i<=N; i++)
        {
            //从左端下落
            if(dpLeft[i]!=0x7fffffff)
            {
                for(int j=i+1; j<=N+1; j++)
                {
                    if(s[j].x1<=s[i].x1&&s[i].x1<=s[j].x2)
                    {
                        if(s[i].h-s[j].h<=MAX)
                        {
                            if(j==N+1)
                            {
                                int cost=dpLeft[i]+s[i].h-s[j].h;
                                ans=min(ans,cost);
                            }
                            else
                            {
                                int cost;
                                //到左端需要的时间
                                cost=dpLeft[i]+s[i].h-s[j].h+s[i].x1-s[j].x1;
                                dpLeft[j]=min(cost,dpLeft[j]);

                                //到右端需要的时间
                                cost=dpLeft[i]+s[i].h-s[j].h+s[j].x2-s[i].x1;
                                dpRight[j]=min(cost,dpRight[j]);
                            }
                        }
                        break;
                    }
                }
            }
            //往右跑
            if(dpRight[i]!=0x7fffffff)
            {
                for(int j=i+1; j<=N+1; j++)
                {
                    if(s[j].x1<=s[i].x2&&s[i].x2<=s[j].x2)
                    {
                        if(s[i].h-s[j].h<=MAX)
                        {
                            if(j==N+1)
                            {
                                int cost=dpRight[i]+s[i].h-s[j].h;
                                ans=min(ans,cost);
                            }
                            else
                            {
                                int cost;
                                //到左端需要的时间
                                cost=dpRight[i]+s[i].h-s[j].h+s[i].x2-s[j].x1;
                                dpLeft[j]=min(cost,dpLeft[j]);

                                //到右端需要的时间
                                cost=dpRight[i]+s[i].h-s[j].h+s[j].x2-s[i].x2;
                                dpRight[j]=min(cost,dpRight[j]);
                            }
                        }
                        break;
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2016-01-20 08:55  Fighting_Heart  阅读(157)  评论(0编辑  收藏  举报