uva437-The Tower of Babylon
题目链接请戳 这里
解题思路
带权DAG上的最大权和路。
可以先对每个木块的三个维度排序方便后续处理。
(思路来自紫书)
dp[i][j]表示以第i个木块为底,j=0/1/2时以长/宽/高 为高,时能组成的最高高度。
代码
#include<stdio.h> #include<string.h> #include<algorithm> #define N 40 using namespace std; int blo[N][3]; int dp[N][3]; int n; int d(int x, int y) { int &ans = dp[x][y]; int u, v; if (ans > 0) return ans; //y决定谁为高 if (y == 0) { ans = blo[x][0]; u = blo[x][1]; v = blo[x][2]; } else if (y == 1) { ans = blo[x][1]; u = blo[x][0]; v = blo[x][2]; } else { ans = blo[x][2]; u = blo[x][0]; v = blo[x][1]; } //因为事先对维度排序,可以减少判断 for (int j = 1; j <= n; j++) for (int k = 0; k <= 2; k++) { if (k == 0 && blo[j][1] < u && blo[j][2] <v) ans = max(ans, d(j, k) + blo[x][y]); else if (k == 1 && blo[j][0] <u && blo[j][2] <v) ans = max(ans, d(j, k) + blo[x][y]); else if (k == 2 && blo[j][0] <u && blo[j][1] <v) ans = max(ans, d(j, k) + blo[x][y]); } return ans; } int main() { int t = 0; while (scanf("%d", &n) != EOF && n) { memset(dp, 0, sizeof(dp)); //现对三个维度排序 for (int i = 1; i <= n; i++) { scanf("%d%d%d", &blo[i][0], &blo[i][1], &blo[i][2]); sort(blo[i], blo[i] + 3); } for (int i = 1; i <= n; i++) for (int k = 0; k <= 2; k++) dp[i][k] = d(i, k); int maxn = 0; for (int i = 1; i <= n; i++) for (int k = 0; k <= 2; k++) maxn = max(maxn, dp[i][k]); printf("Case %d: maximum height = ", ++t); printf("%d\n", maxn); } return 0; }