1. 程式人生 > >POJ 1661 解題報告

POJ 1661 解題報告

這道題可以看做是DP也可以看成模擬。從上往下看每個平臺能否到達,是否遮擋,是否到地。程式碼寫得重複很多,應該可以簡潔許多。

需要注意的地方是這裡把出發點也看做了一個平臺,這樣按照平臺高度排序的時候需要排N+1個(而不是N個)。

1661 Accepted 180K 0MS C++ 3018B
/* 
ID: thestor1 
LANG: C++ 
TASK: poj1661 
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>

using namespace std;

const int MAXN = 1000 + 1;
const int INF = 40000000;

class Platform
{
public:
	int x1, x2, y;
	Platform() {}
	Platform(int x1, int x2, int y) : x1(x1), x2(x2), y(y) {}

	inline bool operator< (const Platform& rhs) const {
		return this->y > rhs.y;
	}
};

bool covered(int x11, int x21, int x12, int x22) {
	if (x12 >= x21 || x22 <= x11) {
		return false;
	}
	return true;
}

int main()
{
	int T;
	scanf("%d", &T);
	Platform platforms[MAXN];
	// DP[i][0] records the minimal time to reach the left end of platforms[i] from (X, Y)
	// DP[i][1] is for the right end
	int DP[MAXN][2];

	int N, X, Y, MAX;
	for (int t = 0; t < T; ++t) {
		scanf("%d%d%d%d", &N, &X, &Y, &MAX);
		platforms[0].x1 = X;
		platforms[0].x2 = X;
		platforms[0].y = Y;

		for (int i = 1; i <= N; ++i) {
			scanf("%d%d%d", &platforms[i].x1, &platforms[i].x2, &platforms[i].y);
		}

		sort(platforms, platforms + N + 1);
		// printf("[debug]platforms:\n");
		// for (int i = 0; i <= N; ++i) {
		// 	printf("%d %d %d\n", platforms[i].x1, platforms[i].x2, platforms[i].y);
		// }

		DP[0][0] = DP[0][1] = 0;
		for (int i = 1; i <= N; ++i) {
			DP[i][0] = DP[i][1] = INF;
		}

		int ans = INF;
		for (int i = 0; i <= N; ++i) {
			bool leftUncovered = true;
			for (int j = i + 1; j <= N && platforms[j].y >= platforms[i].y - MAX; ++j) {
				if (platforms[j].x1 <= platforms[i].x1 && platforms[i].x1 <= platforms[j].x2) {
					DP[j][0] = min(DP[j][0], DP[i][0] + (platforms[i].y - platforms[j].y) + abs(platforms[j].x1 - platforms[i].x1));
					DP[j][1] = min(DP[j][1], DP[i][0] + (platforms[i].y - platforms[j].y) + abs(platforms[j].x2 - platforms[i].x1));

					leftUncovered = false;
					break;
				}
			}

			// if the left side of platforms[i] can fall to ground (y == 0)
			if (leftUncovered && platforms[i].y - MAX <= 0) {
				ans = min(ans, DP[i][0] + platforms[i].y);
			}

			bool rightUncovered = true;
			for (int j = i + 1; j <= N && platforms[j].y >= platforms[i].y - MAX; ++j) {
				if (platforms[j].x1 <= platforms[i].x2 && platforms[i].x2 <= platforms[j].x2) {
					DP[j][0] = min(DP[j][0], DP[i][1] + (platforms[i].y - platforms[j].y) + abs(platforms[j].x1 - platforms[i].x2));
					DP[j][1] = min(DP[j][1], DP[i][1] + (platforms[i].y - platforms[j].y) + abs(platforms[j].x2 - platforms[i].x2));

					rightUncovered = false;
					break;
				}
			}

			// if the right side of platforms[i] can fall to ground (y == 0)
			if (rightUncovered && platforms[i].y - MAX <= 0) {
				ans = min(ans, DP[i][1] + platforms[i].y);
			}
		}

		// printf("[debug]DP:\n");
		// for (int i = 0; i <= N; ++i) {
		// 	printf("DP[%d]: %d, %d\n", i, DP[i][0], DP[i][1]);
		// }

		printf("%d\n", ans);
	}
	return 0;
}