HDU 1069 Monkey and Banana 解题心得
原题:
Description
一组研究人员正在设计一项实验,以测试猴子的智商。他们将挂香蕉在建筑物的屋顶,同时,提供一些砖块给这些猴子。如果猴子足够聪明,它应当能够通过合理的放置一些砖块建立一个塔,并爬上去吃他们最喜欢的香蕉。
研究人员有n种类型的砖块,每种类型的砖块都有无限个。第i块砖块的长宽高分别用xi,yi,zi来表示。 同时,由于砖块是可以旋转的,每个砖块的3条边可以组成6种不同的长宽高。
在构建塔时,当且仅当A砖块的长和宽都分别小于B砖块的长和宽时,A砖块才能放到B砖块的上面,因为必须留有一些空间让猴子来踩。
你的任务是编写一个程序,计算猴子们最高可以堆出的砖块们的高度。
Input
输入文件包含多组测试数据。
每个测试用例的第一行包含一个整数n,代表不同种类的砖块数目。n<=30.
接下来n行,每行3个数,分别表示砖块的长宽高。
当n= 0的时候,无需输出任何答案,测试结束。
Output
对于每组测试数据,输出最大高度。格式:Case 第几组数据: maximum height = 最大高度
Sample Input
1
10 20 30
2
6 8 10
5 5 5
7
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27
0
2
6 8 10
5 5 5
7
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27
0
Sample Output
Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342
Case 3: maximum height = 28
Case 4: maximum height = 342
分析:dp[i]=max( for(j=i-1;j>=0;j--) dp[j]+block[i].h ,dp[i] )
输入一组数组要存入6个数据,分别对应6中不同的摆放方式,(其实也可以只要存三组同时保证宽小于长)->排序->再用状态转移方程:
dp[i] 表示以第i个砖作为底部可以累加的最大高度
dp[i]=max( for(j=i-1;j>=0;j--) dp[j]+block[i].h ,dp[i] )
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; // 状态转移方程: dp[i]=max( for(j=i-1;j>=0;j--) dp[j]+block[i].h ,dp[i] ) // 复杂度 n^2 struct blocks { int a, b, h; bool operator <(const blocks &x)const { if (a == x.a){ return b < x.b; } else{ return a < x.a; } } }block[200]; int dp[200]; bool check(const blocks &x, const blocks &y) { if (x.a < y.a&&x.b < y.b) return 1; return 0; } // dp[i] 表示以第i个砖作为底部可以累加的最大高度 int main() { int kase; int k = 1; while (cin >> kase&&kase != 0) { int x, y, z; int n = kase * 6; for (int i = 0; i < n;) { scanf("%d%d%d", &x, &y, &z); block[i].a = x, block[i].b = y, block[i].h = z, i++; block[i].a = x, block[i].b = z, block[i].h = y, i++; block[i].a = y, block[i].b = x, block[i].h = z, i++; block[i].a = y, block[i].b = z, block[i].h = x, i++; block[i].a = z, block[i].b = x, block[i].h = y, i++; block[i].a = z, block[i].b = y, block[i].h = x, i++; } sort(block, block + n); int Max = 0; for (int i = 0; i < n; i++) { dp[i] = block[i].h; for (int j = i - 1; j >= 0; j--) { if (check(block[j], block[i]) && dp[i] < dp[j] + block[i].h) dp[i] = dp[j] + block[i].h; } if (Max < dp[i]) Max = dp[i]; } printf("Case %d: maximum height = %d\n", k++, Max); } return 0; }