poj_1661Help Jimmy

Help Jimmy
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 7549   Accepted: 2405

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
Jimmy 跳到一块板上后,可以有两种选择,向左走,或向右走。走到左端和走到右端所需的时间,是很容易算的。如果我们能知道,以左端为起点到达地面的最短时间,和以右端为起点到达地面的最短时间,那么向左走还是向右走,就很容选择了。因此,整个问题就被分解成两个子问题,即Jimmy 所在位置下方第一块板左端为起点到地面的最短时间,和右端为起点到地面的最短时间。这两个子问题在形式上和原问题是完全一致的。将板子从上到下从1 开始进行无重复的编号(越高的板子编号越小,高度相同的几块板子,哪块编号在前无所谓),那么,和上面两个子问题相关的变量就只有板子的编号,所以,本题目的“状态”就是板子编号,而一个“状态”对应的“值”有两部分,是两个子问题的解,即从该板子左端出发到达地面的最短时间,和从该板子右端出发到达地面的最短时间。不妨认为Jimmy 开始的位置是一个编号为0,长度为0 的板子,假设LeftMinTime(k)表示从k 号板子左端到地面的最短时间,RightMinTime(k)表示从k 号板子右端到地面的最短时间,那么,求板子k 左端点到地面的最短时间的方法如下:
if ( 板子k 左端正下方没有别的板子) {
    if( 板子k 的高度 h(k) 大于Max)
        LeftMinTime(k) = ∞;
    else
        LeftMinTime(k) = h(k);
}
else if( 板子k 左端正下方的板子编号是m )
    LeftMinTime(k) = h(k)-h(m) + Min( LeftMinTime(m) + Lx(k)-Lx(m), RightMinTime(m) + Rx(m)-Lx(k));
}
    上面,h(i)就代表i 号板子的高度,Lx(i)就代表i 号板子左端点的横坐标,Rx(i)就代表i号板子右端点的横坐标。那么 h(k)-h(m) 当然就是从k 号板子跳到m 号板子所需要的时间,Lx(k)-Lx(m) 就是从m 号板子的落脚点走到m 号板子左端点的时间,Rx(m)-Lx(k)就是从m号板子的落脚点走到右端点所需的时间。
    求RightMinTime(k)的过程类似。
    不妨认为Jimmy 开始的位置是一个编号为0,长度为0 的板子,那么整个问题就是要求LeftMinTime(0)。
    输入数据中,板子并没有按高度排序,所以程序中一定要首先将板子排序。


point坐标写错N个,WA N次。没有注意从起点直接下落,wa。。。

为爱debug,期末要挂科。。。

代码:



#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 999999;
struct Point{
	int x;
	int y;
	int height;
}point[1005];

bool cmp(Point a, Point b)
{
	return a.height < b.height;
}
int dp[1005][1005];
int n, num;

void MinTime()
{
	int next_x, next_y;
	bool flag_x, flag_y;
	dp[1][point[1].x] = point[1].height;
	dp[1][point[1].y] = point[1].height;
	for(int i = 2; i <= n + 1; i++)
	{
		flag_x = false;
		for(int j = i - 1; j >= 1; j--)
		{
			if(point[j].x <= point[i].x && point[i].x <= point[j].y)
			{
				next_x = j;
				flag_x = true;
				break;
			}
		}
		if(flag_x)
		{
			if(point[i].height - point[next_x].height <= num)  //注意中途也要考虑小于最大下降高度,摔死老鼠怎么办?
				dp[i][point[i].x] = point[i].height - point[next_x].height + min(dp[next_x][point[next_x].x]+point[i].x-point[next_x].x,dp[next_x][point[next_x].y]+point[next_x].y-point[i].x);
			else dp[i][point[i].x] = MAX;
		}
		else
		{
			if(point[i].height > num)
				dp[i][point[i].x] = MAX;
			else
				dp[i][point[i].x] = point[i].height;
		}


		flag_y = false;
		for(int j = i - 1; j >= 1; j--)
		{
			if(point[j].y >= point[i].y && point[i].y >= point[j].x)
			{
				next_y = j;
				flag_y = true;
				break;
			}
		}
		if(flag_y)
		{
			if(point[i].height - point[next_y].height <= num)
				dp[i][point[i].y] = point[i].height - point[next_y].height + min(dp[next_y][point[next_y].x]+point[i].y-point[next_y].x,dp[next_y][point[next_y].y]+point[next_y].y-point[i].y);
			else dp[i][point[i].y] = MAX;
		}
		else
		{
			if(point[i].height > num)
			{
				dp[i][point[i].y] = MAX;
			}
			else
			{
				dp[i][point[i].y] = point[i].height;
			}
		}
	}
}

int main()
{
	freopen("in.txt","r",stdin);
	int t, x, y, i;
	cin >> t;
	while(t--)
	{
		memset(dp, 0, sizeof(dp));
		memset(point, 0, sizeof(point));
		cin >> n >> x >> y >> num;
		for(i = 1; i <= n; i++)
		{
			cin >> point[i].x >> point[i].y >> point[i].height;
		}
		point[n+1].x = point[n+1].y = x;
		point[n+1].height = y;
		sort(point + 1, point + n + 2, cmp);
		MinTime();
		cout<<dp[n+1][point[n+1].x]<<endl;
	}
	return 0;
}



原文地址:https://www.cnblogs.com/lgh1992314/p/5835269.html