Help Jimmy POJ - 1661

dp首先要确定状态。
竖直方向所用时间是一定的,可以最后直接加Y。

刚开始想的是从高到低,发现这样无法确定状态。
从上往下,每一个平面有可能从上面多个平面推出。
而从下往上,一个平面只能从下面一个平面推出。

将0,Y都变成一个平面。

原问题 从第0层到n+1层的时间。
子问题 从第i层到n+1层的时间。

因为同一层有左右两个状态,所以需要二维数组。
状态:dp[i][0], 从i层左边到地面所用最短时间。
dp[i][1] 从i层右边到地面所用最短时间。

   #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x3f3f3f3f
    using namespace std;
    struct node{
    	int x1,x2,y;
    }ns[1100];
    bool cmp(node a,node b)
    {
    	return a.y<b.y;
    }
    int dp[1100][2];
    int main()
    {
    	int t;
    	cin>>t;
    	while(t--)
    	{
    		int n,X,Y,maxn;
    		scanf("%d%d%d%d",&n,&X,&Y,&maxn);
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%d%d%d",&ns[i].x1,&ns[i].x2,&ns[i].y);
    		}
    		ns[0].x1=X,ns[0].x2=X,ns[0].y=Y;
    		ns[n+1].x1=-20000,ns[n+1].x2=20000,ns[n+1].y=0;
    		sort(ns,ns+n+2,cmp);
    		memset(dp,inf,sizeof(dp));
    		dp[0][0]=dp[0][1]=0;
    		for(int i=1;i<=n+1;i++)
    		{
    			for(int j=i-1;j>=0&&ns[i].y-ns[j].y<=maxn;j--)
    			{
    			    if(ns[j].x1<=ns[i].x1&&ns[i].x1<=ns[j].x2)
    			    {
    			    	if(j==0)
    				    {
    					    dp[i][0]=0;
    					    
    					}
    				
    				    else dp[i][0]=min(dp[j][0]+ns[i].x1-ns[j].x1,dp[j][1]+ns[j].x2-ns[i].x1);
    				    break;//只能到达下面最高的满足条件的平面。
    					//两个break 不是同时满足,所以dp[i][0]和dp[i][1]需要分开求。 
    				}
    				
    			}
    			for(int j=i-1;j>=0&&ns[i].y-ns[j].y<=maxn;j--)
    			{
    			    if(ns[j].x1<=ns[i].x2&&ns[i].x2<=ns[j].x2)
    			    {
    			    	if(j==0)
    				    {
    					dp[i][1]=0;
    				    }
    				    else  
    				    {
    					    dp[i][1]=min(dp[j][0]+ns[i].x2-ns[j].x1,dp[j][1]+ns[j].x2-ns[i].x2);
    				    }
    				    break;
    				}
    				
    			}
    		}
    	
    			
    		printf("%d\n",min(dp[n+1][1],dp[n+1][0])+Y);	
    	}
     } 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值