n ≤ 30 種積木,每種無限供應,尺寸 (x,y,z)。積木可旋轉(任兩維為底,第三維為高)。堆疊規則:上層積木**長寬嚴格小於**下層對應邊。求最高塔高度。
6n 個「底面長寬+高度」三元組。≥ 寬(或固定順序),避免重複朝向。dp[i] = height[i] + max{dp[j] | j。max(dp[i])。#includeusing namespace std; struct Block { int x, y, h; }; // x≥y 為底面長寬,h 為高 bool cmp(Block a, Block b) { if (a.x != b.x) return a.x < b.x; return a.y < b.y; } int main() { int n, cas = 1; while (cin >> n, n) { vector blocks; for (int i=0;i > a >> b >> c; // 6 種朝向 blocks.push_back({max(a,b), min(a,b), c}); blocks.push_back({max(a,c), min(a,c), b}); blocks.push_back({max(b,c), min(b,c), a}); blocks.push_back({max(b,a), min(b,a), c}); // 重複但無妨 blocks.push_back({max(c,a), min(c,a), b}); blocks.push_back({max(c,b), min(c,b), a}); } sort(blocks.begin(), blocks.end(), cmp); int m = blocks.size(); vector dp(m); int ans = 0; for (int i=0;i blocks[j].x && blocks[i].y > blocks[j].y) dp[i] = max(dp[i], dp[j] + blocks[i].h); ans = max(ans, dp[i]); } printf("Case %d: maximum height = %d\n", cas++, ans); } return 0; }
x≥y,排序時長優先、寬次之。n=30 → 180 塊,O(m²) = 32400 極快。