POJ 1661 Help Jimmy dp

来源:互联网 发布:淘宝助理可以加水印吗 编辑:程序博客网 时间:2024/06/01 10:29

题目链接

思路:

       对于这种有两种走法的我们需要进行两个状态的dp,也就是说一个表示从左到地面的最小值,一个是从右到地面你的最小值,然后维护二者的最小值.

还是那句话,对于起始位置确定的末位置不确定的我们一般倒着往前dp,最后直接输出起始位置的最小值就好

dp[i][0]表示第i个平台从左走到地面的最小值,dp[i][1]表示从右走到地面的最小值.

对于这个题还有很多需要注意的地方,那就是每个平台只能走到他下面未被覆盖的第一个平台上面,我一开始按照从上向下走的不知道怎么判断这一块能不能由他上面的那块转化来...尤其是有多块都可以走来的情况,从下往上的话,那么对于当前的平台找到他下面的第一个平台就直接停止.而且对于没找到的平台需要判断一下能否直接走到地如果可以就把距离设为到地的距离否则就是inf

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define inf 0x3f3f3f3fusing namespace std;const int maxn=1111;int dp[maxn][2];int n,x,y,maxh;struct node{int x1,x2,h;}q[maxn];bool cmp(node a,node b){return a.h<b.h;}int main(){int t;scanf("%d",&t);while(t--){memset(dp,0,sizeof(dp));scanf("%d %d %d %d",&n,&x,&y,&maxh);q[0].x1=q[0].x2=x;q[0].h=y;for(int i=1;i<=n;i++)scanf("%d %d %d",&q[i].x1,&q[i].x2,&q[i].h);sort(q,q+1+n,cmp);bool flag;for(int i=0;i<=n;i++){flag=false;for(int j=i-1;j>=0;j--){if(q[i].h-q[j].h<=maxh){if(q[i].x1>=q[j].x1&&q[i].x1<=q[j].x2){dp[i][0]=q[i].h-q[j].h+min(dp[j][0]+q[i].x1-q[j].x1,dp[j][1]+q[j].x2-q[i].x1);flag=true;}}if(flag)break;}if(!flag){if(q[i].h<=maxh)dp[i][0]=q[i].h;elsedp[i][0]=inf;}flag=false;for(int j=i-1;j>=0;j--){if(q[i].h-q[j].h<=maxh){if(q[i].x2>=q[j].x1&&q[i].x2<=q[j].x2){dp[i][1]=q[i].h-q[j].h+min(dp[j][0]+q[i].x2-q[j].x1,dp[j][1]+q[j].x2-q[i].x2);flag=true;}}if(flag)break;}if(!flag)//没找到平台过度就直接判断能否到大地面{if(q[i].h<=maxh)dp[i][1]=q[i].h;elsedp[i][1]=inf;}}/*for(int i=0;i<=n;i++){printf("%d %d %d %d\n",q[i].h,i,dp[i][0],dp[i][1]);}*/printf("%d\n",min(dp[n][0],dp[n][1]));}return 0;}/*13 8 17 200 10 130 10 84 14 3*/


1 0