本题类似于嵌套矩形问题,笔者受嵌套矩形问题启发,解决了本道题目。把本题中所有矩形种类求出来(3*n),接下来就是嵌套矩形问题了。
/*
【思路分析】
先把长方体的所有种类存储起来,然后用这些长方体进行dp
大指向小则有边,建立图,因为总是严格的大指向小,所以
一定是有向无环图(DAG)。注意一个长方体可能是多种长方
体,比如(10,20,30),分别以10,20,30为高,则有3种长方体。
题目虽说每个长方体都有无限多个,其实最多也只能用3*n个,
因为如果一个被用了,不可能再用和他完全一样的长方体了。
d(i)表示从第i点出发的最长路
d(i)=max{d(j)+rec[i].z | (i,j)∈E}
*/
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=50;//最多只有30个,不妨稍微搞大点
int n;
int d[maxn*3];
typedef struct{
int x;
int y;
int z;//不妨把x,y当成底座,z当成高
}rectangular;
rectangular rec[maxn*3];
int graph[3*maxn][3*maxn];
int dp(int i){
int &ans=d[i];
if(ans>0) return ans;//注意本题要用记忆化搜索,直接递归会超时
ans=rec[i].z;
for(int j=1;j<=3*n;j++){
if(graph[i][j]){
ans=max(ans,dp(j)+rec[i].z);
}
}
return ans;
}
int main()
{
int kase=0;
while(cin>>n && n){
int cnt=0;
int xx,yy,zz;
//把n个矩形块搞成3n个矩形块(即使有重复也没事),比如(20,20,20)搞成三个都一样
//因为在建立图的时候,重复的之间是不会建立边的
for(int i=1;i<=n;i++){
cin>>xx>>yy>>zz;
++cnt;
rec[cnt].x=xx;rec[cnt].y=yy;rec[cnt].z=zz;d[cnt]=rec[cnt].z;
++cnt;
rec[cnt].x=zz;rec[cnt].y=yy;rec[cnt].z=xx;
++cnt;
rec[cnt].x=xx;rec[cnt].y=zz;rec[cnt].z=yy;
}
//建图
memset(graph,0,sizeof(graph));
for(int i=1;i<=3*n;i++){
for(int j=1;j<=3*n;j++){
if((rec[i].x<rec[j].x && rec[i].y<rec[j].y) || (rec[i].x<rec[j].y && rec[i].y<rec[j].x)){
graph[i][j]=rec[j].z;//i,j之间有边,我们可以把边权重指定为j对应的z值
}
}
}
//dp
memset(d,0,sizeof(d));
int ans=0;
for(int i=1;i<=3*n;i++){
ans=max(ans,dp(i));
}
cout<<"Case "<<++kase<<": maximum height = "<<ans<<endl;
}
return 0;
}