POJ - 1661 Help Jimmy (dp)

题目链接:http://poj.org/problem?id=1661点击打开链接

Help Jimmy
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 12942 Accepted: 4300

Description

"Help Jimmy" 是在下图所示的场景上完成的游戏。 

场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。 

Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。 

设计一个程序,计算Jimmy到底地面时可能的最早时间。 

Input

第一行是测试数据的组数t(0 <= t <= 20)。每组测试数据的第一行是四个整数N,X,Y,MAX,用空格分隔。N是平台的数目(不包括地面),X和Y是Jimmy开始下落的位置的横竖坐标,MAX是一次下落的最大高度。接下来的N行每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示平台的高度,X1[i]和X2[i]表示平台左右端点的横坐标。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1..N)。所有坐标的单位都是米。 

Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。 

Output

对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。

Sample Input

1
3 8 17 20
0 10 8
0 10 13
4 14 3

Sample Output

23


哇被这道题坑了好久

主要在于对他的边界问题的纠结。。

说几个点吧

dp【i】【j】记录的是第i个木板的左右边界情况 0表示左 1表示右

可以将起点看做一个木板

一直纠结于+1-1边界问题。。最后才知道其实不需要考虑那些就是对的。。

注意记录状态 用flag记录每个dp点下面有没有木板挡着他 如果挡着他不能直接到地面

然后注意等于号。。两块相邻木板端点相同是可以到达的?? 感觉跟题意不太符啊 可是就是因为这组数据然后改了就过了

1
2 8 20 15
1 7 10

8 20 10

ans:20

然后他掉下来的过程中是不能移动的。。

跟是男人就下100层还是有点区别。。

有两种思路的写法 一种是由当前确定的最优节点往下dp

另一种是对上面最优节点节点进行dp

#include <stdio.h>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
struct xjy
{
	int x1;
	int x2;
	int y;
	bool operator < (const xjy &r)const
	{
		return y>r.y;
	}
};
int dp[1111][2];
int flag[1111][2];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		for(int i=0;i<1111;i++)
			for(int j=0;j<2;j++)
			{
				dp[i][j]=99999999;
				flag[i][j]=0;
			}
		vector<xjy > s;
		int n,x,y,maxx;
		scanf("%d%d%d%d",&n,&x,&y,&maxx);
		xjy mid;
		mid.x1=x;
		mid.x2=x;
		mid.y=y;
		s.push_back(mid);
		for(int i=0;i<n;i++)
		{
			scanf("%d%d%d",&mid.x1,&mid.x2,&mid.y);
			s.push_back(mid);
		}
		sort(s.begin(),s.end());
		dp[0][0]=0;
		dp[0][1]=0;
		for(int i=0;i<=n;i++)
		{
			for(int j=i-1;j>=0;j--)
			{
				if(s[j].y-s[i].y>maxx)
				{
					break;
				}
				if(s[i].x2>=s[j].x1&&s[i].x1<=s[j].x1&&flag[j][0]==0)
				{
					flag[j][0]=1;
					dp[i][0]=min(dp[i][0],dp[j][0]+s[j].y-s[i].y+s[j].x1-s[i].x1);
					dp[i][1]=min(dp[i][1],dp[j][0]+s[j].y-s[i].y+s[i].x2-s[j].x1);
				}
				if(s[i].x1<=s[j].x2&&s[j].x2<=s[i].x2&&flag[j][1]==0)
				{
					flag[j][1]=1;
					dp[i][0]=min(dp[i][0],dp[j][1]+s[j].y-s[i].y+s[j].x2-s[i].x1);
					dp[i][1]=min(dp[i][1],dp[j][1]+s[j].y-s[i].y+s[i].x2-s[j].x2);
				}
			}
		}
		int ans=99999999;
		int l=s[n].x1;
		int r=s[n].x2;
		for(int i=n;i>=0;i--)
		{
			if(!flag[i][0]&&s[i].y<=maxx)
			{
				ans=min(ans,dp[i][0]+s[i].y);
			}
			if(!flag[i][1]&&s[i].y<=maxx)
			{
				ans=min(ans,dp[i][1]+s[i].y);
			}
		}
		printf("%d\n",ans);
	}
}

#include <stdio.h>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
struct xjy
{
	int x1;
	int x2;
	int y;
	bool operator < (const xjy &r)const
	{
		return y>r.y;
	}
};
int dp[1111][2];
int flag[1111][2];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		for(int i=0;i<1111;i++)
			for(int j=0;j<2;j++)
			{
				dp[i][j]=9999999;
				flag[i][j]=0;
			}
		vector<xjy > s;
		int n,x,y,maxx;
		scanf("%d%d%d%d",&n,&x,&y,&maxx);
		xjy mid;
		mid.x1=x;
		mid.x2=x;
		mid.y=y;
		s.push_back(mid);
		for(int i=0;i<n;i++)
		{
			scanf("%d%d%d",&mid.x1,&mid.x2,&mid.y);
			s.push_back(mid);
		}
		sort(s.begin(),s.end());
		dp[0][0]=0;
		dp[0][1]=0;
		for(int i=0;i<=n;i++)
		{
			for(int j=i+1;j<=n;j++)
			{
				if(s[i].y-s[j].y>maxx)
				{
					break;
				}
				if(s[i].x1>=s[j].x1&&s[i].x1<=s[j].x2&&flag[i][0]==0)
				{
					flag[i][0]=1;
					dp[j][0]=min(dp[j][0],dp[i][0]+s[i].y-s[j].y+s[i].x1-s[j].x1);
					dp[j][1]=min(dp[j][1],dp[i][0]+s[i].y-s[j].y+s[j].x2-s[i].x1);
				}
				if(s[j].x1<=s[i].x2&&s[i].x2<=s[j].x2&&flag[i][1]==0)
				{
					flag[i][1]=1;
					dp[j][0]=min(dp[j][0],dp[i][1]+s[i].y-s[j].y+s[i].x2-s[j].x1);
					dp[j][1]=min(dp[j][1],dp[i][1]+s[i].y-s[j].y+s[j].x2-s[i].x2);
				}
			}
		}
		int ans=9999999;
		for(int i=n;i>=0;i--)
		{
			if(!flag[i][0]&&s[i].y<=maxx)
			{
				ans=min(ans,dp[i][0]+s[i].y);
			}
			if(!flag[i][1]&&s[i].y<=maxx)
			{
				ans=min(ans,dp[i][1]+s[i].y);
			}
		}
		printf("%d\n",ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值