POJ 1661 解題報告
阿新 • • 發佈:2019-01-23
這道題可以看做是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; }