其他分享
首页 > 其他分享> > POJ1661 dp

POJ1661 dp

作者:互联网

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

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

设计一个程序,计算Jimmy到底地面时可能的最早时间。
这是一道DP问题,首先是要分析每一步的转态,首先我们很容易想到对于每一个平台,我们往左走可以到达平台和往右走可以到达的平台是确定的。我们就可以先预处理出这一部分。接着我们考虑到对于每平台,我们都有两种走法,左走和右走.然后走到下一个平台后,我们又是有左走和右走两个走法。如此反复直到最下面地面。
用f[i][0]表示到达i这个平台的左端点时的最少时间
用f[i][1]表示到达i这个平台的右端点时的最少时间
为什么是要表示到端点呢?因为到达板的位置不一样,往下走的时间也不一样,所以选择设计状态是到他们都会达到的端点时的状态。
然后我们从f[i][0]转移到j平台上我们就是从i平台的左端点走到下面的平台,但是走到下面的平台我们可以走到左端点,也可以走到右端点,这就分别都转移就可以了;
jump数组就是表示从i平台左端点往下走是哪个平台,从右端点是哪个平台。

f[jump[i][0]][0] = min(f[jump[i][0]][0], f[i][0] + (xian[i].h - xian[jump[i][0]].h) + (xian[i].x1 - xian[jump[i][0]].x1));
f[jump[i][0]][1] = min(f[jump[i][0]][1], f[i][0] + (xian[i].h - xian[jump[i][0]].h) + (xian[jump[i][0]].x2 - xian[i].x1));

只要实现了上面的转移方程所需要的jump数组,在循环转移一次,最后也就答案出来了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>
#include<stack>
#define ll long long
using namespace std;
const long long max_ = 2e3 + 7;
inline int read() {
	int s = 0, f = 1;
	char ch = getchar();
	while (ch<'0' || ch>'9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0'&&ch <= '9') {
		s = s * 10 + ch - '0';
		ch = getchar();
	}
	return s * f;
}
struct k {
	int x1, x2, h;
}xian[1000 + 50];
int n, x, y, MAX, xiann = 0;
bool cmp(const k &t1, const k &t2) {
	return t1.h > t2.h;
}
int jump[1000 + 50][2], f[1000 + 3][4];
int main() {
	int T; 
	while (scanf_s("%d", &T) != EOF) {
		while (T--) {
			int first, temptime = 0, xmax = -1;
			n = read(), x = read(), y = read(), MAX = read();
			x += 20000;
			for (int i = 1; i <= n; i++) {
				xian[i].x1 = (read() + 20000);
				xian[i].x2 = (read() + 20000);
				xmax = max(xmax, xian[i].x2);
				xian[i].h = read();
			}
			sort(xian + 1, xian + 1 + n, cmp);
			xian[n + 1].x1 = -20000;
			xian[n + 1].x2 = 1e9;
			xian[n + 1].h = 0;

			for (int i = 0; i <= n + 1; i++) {
				for (int j = 0; j <= 2; j++) {
					f[i][j] = 1e9;
				}
			}
			first = 0;
			for (int i = 1; i <= n; i++) {
				if (xian[i].x1 <= x && xian[i].x2 >= x) {
					first = i;
					temptime = y - xian[i].h;
					break;
				}
			}
			if (first == 0) {
				cout << y << endl;
				continue;
			}
			for (int i = 1; i <= n; i++) {
				for (int j = i + 1; j <= n + 1; j++) {
					if (jump[i][0] != 0 && jump[i][1] != 0) break;
					if (xian[j].h < xian[i].h && xian[j].x1 <= xian[i].x1 && xian[j].x2 >= xian[i].x1&&xian[i].h - xian[j].h <= MAX && jump[i][0] == 0) {
						//i这块板的左边第一个可以跳的
						jump[i][0] = j;
					}
					if (xian[j].h < xian[i].h && xian[j].x1 <= xian[i].x2 && xian[j].x2 >= xian[i].x2&&xian[i].h - xian[j].h <= MAX && jump[i][1] == 0) {
						//i这块板的右边第一个可以跳的
						jump[i][1] = j;
					}
				}
			}
			f[first][0] = (y - xian[first].h) + (x - xian[first].x1);
			f[first][1] = (y - xian[first].h) + (xian[first].x2 - x);
			int flag = 0;
			for (int i = first; i <= n; i++) {
				if (flag == 1 && xian[i].h == xian[first].h)continue;
				if (i == first) {
					flag = 1;
				}
				if (jump[i][0] != 0) {
					if (jump[i][0] == n + 1) {
						f[n + 1][0] = min(f[n + 1][0], f[i][0] + xian[i].h);
						f[n + 1][1] = min(f[n + 1][1], f[i][0] + xian[i].h);
					}
					else {
						f[jump[i][0]][0] = min(f[jump[i][0]][0], f[i][0] + (xian[i].h - xian[jump[i][0]].h) + (xian[i].x1 - xian[jump[i][0]].x1));
						f[jump[i][0]][1] = min(f[jump[i][0]][1], f[i][0] + (xian[i].h - xian[jump[i][0]].h) + (xian[jump[i][0]].x2 - xian[i].x1));
					}
				}
				if (jump[i][1] != 0) {
					if (jump[i][1] == n + 1) {
						f[n + 1][0] = min(f[n + 1][0], f[i][1] + xian[i].h);
						f[n + 1][1] = min(f[n + 1][1], f[i][1] + xian[i].h);
					}
					else {
						f[jump[i][1]][0] = min(f[jump[i][1]][0], f[i][1] + (xian[i].h - xian[jump[i][1]].h) + (xian[i].x2 - xian[jump[i][1]].x1));
						f[jump[i][1]][1] = min(f[jump[i][1]][1], f[i][1] + (xian[i].h - xian[jump[i][1]].h) + (xian[jump[i][1]].x2 - xian[i].x2));
					}
				}
			}
			cout << min(f[n + 1][1], f[n + 1][0]) << endl;
			for (int i = 0; i <= n; i++) {
				jump[i][1] = jump[i][0] = xian[i].h = xian[i].x1 = xian[i].x2 = 0;
			}
		}
	}
	return 0;
}

标签:int,平台,xian,POJ1661,jump,端点,include,dp
来源: https://blog.csdn.net/qq_43804974/article/details/101468226