大概题意:猴子想拿到房顶的香蕉,有几种不同的block可用,每种可用若干个,每种block有三个参数:x,y,z。猴子可以将面积大的放下层,然后再放上一个面积小的,然后……这样可以增加最后能达到的高度。但是有个要求:上面的block的长和宽都必须严格的小于下面的block。每个block的两个参数当做长和宽时,另一个参数做高度用。
状态方程:dp[i]=max{ dp[i];f[j][i]} 0<=j<i<n;
f[j][i]={dp[j]+block[i].h(x[j]<x[i]&&y[j]<y[i]);0(初始化)};
//wa了一次,因为忘记把f[][]初始化。。
//状态方程没想好就打上去了,测试数据时又改的。。
//因为每个block三个参数可以两两当长或宽的用,所以每次输入都增加了6个block:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,ans;
int a,b,c;
struct Block{
int x,y,h;
};
Block block[186];
int dp[186];
int f[186][186];
int max(int x,int y){
return (x>y?x:y);
}
bool cmp(Block a,Block b){
if(a.x!=b.x) return a.x<b.x;
else return a.y<b.y;
}
int t=0;
int main(){
while(~scanf("%d",&n),n){
++t;
int index=0;
for(int i=0;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
block[index].x=a,block[index].y=b,block[index++].h=c;
block[index].x=a,block[index].y=c,block[index++].h=b;
block[index].x=b,block[index].y=a,block[index++].h=c;
block[index].x=b,block[index].y=c,block[index++].h=a;
block[index].x=c,block[index].y=a,block[index++].h=b;
block[index].x=c,block[index].y=b,block[index++].h=a;
}
sort(block,block+index,cmp);
dp[0]=block[0].h;
ans=dp[0];
memset(f,0,sizeof(f));
for(int i=1;i<index;i++){
dp[i]=block[i].h;
for(int j=0;j<i;j++){
if(block[i].x>block[j].x&&block[i].y>block[j].y){
f[j][i]=block[i].h+dp[j];
}
dp[i]=max(dp[i],f[j][i]);
}
if(dp[i]>ans) ans=dp[i];
}
printf("Case %d: maximum height = %d\n",t,ans);
}
return 0;
}