解题报告 之 UVA437 The Tower of Babylon

解题报告 之 UVA437 The Tower of Babylon

Description

Download as PDF

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  . 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. 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.

Input and Output

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  ,  and  .

Input is terminated by a value of zero (0) for n.

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 "Casecase: maximum height =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

Sample Output

Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342


题目大意:有n个立方体,给出长宽高,每种有无限个。现在要将这些立方体重叠起来,力求有最大的高度。放上面的立方体的底面长宽必须严格小于下面立方体的底面长宽,但以那一条边为高可以自由决定。


分析:DP的DAG模型第二道例题,一看就是dp,但是还是有很多感觉迷糊的地方,一开始没想出来。先感觉是嵌套矩形模型,但是又有问题,详细研究了紫书,发现是dp[i][j]表示以第i个立方体为顶端,且以第j大的边为高。

一开始状态转移不是很明确,主要是纠结在边界位置,感觉如果dp[i][j]的状态来自其他所有能放在它下面的立方体的话,那么它下面的立方体可能有很多种情况,而且后面可能会再度更新,可能造成错误。但是看了紫书的思路之后发现其实会有一个立方体是只能作为基底的,那么这个立方体作为边界,就不会有问题了。那么状态转移就是遍历其他所有立方体,如果满足底面严格包含关系就可以试更新dp[i][j],即

if(v1[0] ans = max(ans, DP(p,q));

其中v1 v2表示两个底面的长宽。

那么又为什么要将高从小到大排序呢?因为如果高比较小的时候,底面长宽就会比较大,所以后来当高较大的时候可能会使用同一个立方体的不同形态(即底面较大的形态)作为底,所以一定要先更新底面大的,再更新底面小的,才能保证最优解。于是乎就可以上代码了。


#include 
#include 
#include 
#include 
using namespace std;

int block[35][4];
int dp[35][4];
int n;

void getLW(int *v, int b, int d)
{
	int cnt = 0;
	for (int i = 0; i < 3; i++)
	{
		if (i != d)
			v[cnt++] = block[b][i];
	}
}

int DP(int i,int j)
{
	int &ans = dp[i][j];
	if (ans != 0)	return ans;
	int v1[2], v2[2];
	getLW(v1, i, j);
	for (int p = 0; p < n; p++)
	{
		for (int q = 0; q < 3; q++)
		{
			getLW(v2, p, q);
			if(v1[0]> n&&n)
	{
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < 3; j++)
				cin >> block[i][j];
			sort(block[i], block[i] + 3);
		}

		memset(dp, 0, sizeof dp);

		int ans = 0;
		for (int i = 0; i < n; i++)
		for (int j = 0; j < 3; j++)
		{
			ans = max(ans, DP(i, j));
		}
		cout <<"Case "<

你可能感兴趣的:(ACM)