题目:http://acm.hdu.edu.cn/showproblem.php?pid=1069
研究人员有n种类型的块,并且每种类型的块都是无限制的。 每个i型块是具有线性尺寸(xi,yi,zi)的矩形固体。 块可以重新定向,使得它的三个维度中的任何两个确定基座的尺寸,而另一个尺寸是高度。
他们想要确保通过堆放块可能的最高的塔可以到达屋顶。 问题在于,在建造塔架时,只能将一块块放置在另一块的顶部,只要上块的两个基座尺寸都严格小于下块的相应底座尺寸,因为必须 一些空间让猴子踩上。 这意味着,例如,面向具有相等尺寸的基座的块不能被堆叠。你的工作就是编写一个程序,用来确定猴子能用一组给定的块建立的最高塔的高度。
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
首先,每个木块可以有3!6种摆法,每种摆法构成1种模型。每种模型最多用一次,因为长宽要越来越小。
而且要先用大的。所以可以以长a从大到小排序。dp[i]表示前i种模型能堆的最大高度,并且第i种在最上面。
dp[i]=max(dp[j]+a[i]),j<i。 从前i种找到最优解再堆上第i个。然后找到以第i个模型为顶点的最高堆。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
using namespace std;
struct tans
{
int a, b, h;
};
tans block[300];
int dp[300];
int len;//保存模型数量
void input(int a,int b,int h)
{
len++;
block[len].a = a;
block[len].b = b;
block[len].h = h;
}
bool cmp(tans m, tans n)//按照长度从大到小
{
if (m.a > n.a)
return 1;
else return 0;
}
int main()
{
int n,s=0,i,aa,bb,hh,j;
while (~scanf("%d", &n) && n != 0)
{
s++; len = 0;
for (i = 0; i < n; i++)
{
scanf("%d%d%d", &aa, &bb, &hh);
input(aa, bb, hh); input(aa, hh, bb);
input(bb, aa, hh); input(bb, hh, aa);
input(hh, aa, bb); input(hh, bb, aa);
}
sort(block + 1, block + 1 + len, cmp);
dp[1] = block[1].h;
for (i = 2; i <= len; i++)
{
dp[i] = block[i].h;//至少为第i个本身的高度
for (j = i-1; j >= 1; j--)
{
if(block[i].a<block[j].a&&block[i].b<block[j].b)//长宽必须满足
dp[i] = max(dp[i], dp[j] + block[i].h);//找到前J块中的最大值
}
}
int mmax = 0;
for (j = 1; j <= len; j++)
mmax = max(mmax, dp[j]);
printf("Case %d: maximum height = %d\n",s, mmax);
}
return 0;
}