转自:https://mp.weixin.qq.com/s/oZVj8lxJH6ZqL4sGCXuxMw
The Tower of Babylon(巴比伦塔)
Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details of this tale have been forgotten. So now, in line with the educational nature of this contest, we will tell you the whole story:
你可能对巴比伦的传说有所耳闻,但如今诸多细节早已随风而逝。现在为了与比赛的教育目的相一致,我们将还原整个故事:
The babylonians had n types of blocks, and an unlimited supply of blocks of each type. Each type-i block was a rectangular solid with linear dimensions (xi,yi,zi). A block could be reoriented so that any two of its three dimensions determined the dimensions of the base and the other dimension was the height.
巴比伦人有 n 种无限供给的砖块,每个砖块 i 是三边为 xi,yi,zi 的长方体,可以以任意两边构成底,第三边为高。
They wanted to construct the tallest tower possible by stacking blocks. The problem was that, in building a tower, one block could only be placed on top of another block as long as the two base dimensions of the upper block were both strictly smaller than the corresponding base dimensions of the lower block. This meant, for example, that blocks oriented to have equal-sized bases couldn’t be stacked.
欲砌砖以筑最高楼。以上一个砖的两底边均严格小于下一个砖的两底边为原则(相等不算数)。
Your job is to write a program that determines the height of the tallest tower the babylonians can build with a given set of blocks.
作为程序员的你来写个bug看看用他给的砖能堆多高。
Input
The input file will contain one or more test cases. The first line of each test case contains an integer n, representing the number of different blocks in the following data set. The maximum value for n is 30. Each of the next n lines contains three integers representing the values xi, yi and zi. Input is terminated by a value of zero (0) for n.
输入:多组数据。每组第一行给出种类数 n,最大30;接下来 n 行每行给出这种砖的长宽高。输入以n==0结束。
Output
For each test case, print one line containing the case number (they are numbered sequentially starting from 1) and the height of the tallest possible tower in the format ‘Case case: maximum height = height’
输出:对于每组数据输出最高塔的高度值,格式Case要求见样例。
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
Sample Output
Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342
//这道题目主要就是学习,进一步dp的思想。
1.首先就是每个砖块都有6种利用方式,所以将其push进去,由于cmp函数中进行了两次比较,所以就push了3次。
2.vector里存的如果是struct,那么可以cmp中的参数就是结构体类型。
3.最重要的就是状态转移!
#include#include #include #include #include using namespace std;struct block{ int a; int b; int height; block(int x, int y, int z){a = x; b = y; height = z;}};struct cmp{ bool operator() (const block& x, const block& y) { return x.a * x.b > y.a * y.b; }};bool yes(block x, block y){ return (x.a > y.a && x.b > y.b) || (x.a > y.b && x.b > y.a);}int main(){ int n, kase = 0; while (~scanf("%d", &n) && n) { vector v; for (int i = 0; i < n; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); //每块都有三种用法 v.push_back(block(a,b,c)); v.push_back(block(a,c,b)); v.push_back(block(b,c,a)); } printf("\n"); sort(v.begin(), v.end(), cmp()); int ans = v[0].height; int dp[100] = { 0}; for (int i = 0; i < v.size(); i++) { dp[i] = v[i].height;//这是不能省的一步 //万一前面没有一个可以匹配的,它本身高度就是本序列的一血 for (int j = 0; j < i; j++)//前面扫荡一遍 if (yes(v[j], v[i]))//双边严格小于 当前i严格小于j dp[i] = max(dp[i], dp[j] + v[i].height); ans = max(ans, dp[i]); } printf("Case %d: maximum height = %d\n", ++kase, ans); }}/**26 8 105 5 5**/
//这个题简直太好了,看懂了之后感觉酣畅淋漓~
面积按从大到小排序,
dp[i]被初始化为本砖块高度;
dp[i]=max{dp[i],dp[j]+height[i]};
两层for循环,i对层,j遍历i之前的,判断i能否放到i之前的砖块上,并且累计自身的高度+上去!
最终答案每次遍历取最大即可。
//学习了!