The Tower of Babylon
题意
\(n\)种箱子,每种箱子都有无数个,有三个属性:长宽高,其中箱子可以任意旋转。
一个箱子能够叠在另一个箱子上的条件是必须有两个属性小于另一个箱子。
求最大能够叠加的高度。
思路
\(n\)只有\(30\),考虑\(n^{2}\)的写法。
由于属性是都小于才可以,所以同样摆法的箱子贡献是相同的。
由于箱子可以旋转,所以只需要提前将箱子的不同摆法看成是不同的箱子。
\(dp[i]\)表示以第\(i\)个箱子为底时能够到达的最大高度。
转移就是从有符合条件的箱子转移。
代码
int n;
int Case=1,dp[44];
struct node{
int x,y,z;
};
vector<node>v;
bool cmp(node a,node b){
if(a.x==b.x){
if(a.y==b.y) return a.z<b.z;
return a.y<b.y;
}
return a.x<b.x;
}
int main() {
while(scanf("%d",&n)!=EOF){
if(!n) break;
rep(i,1,n){
int x=read,y=read,z=read;
v.push_back({x,y,z});
v.push_back({z,y,x});
v.push_back({x,z,y});
v.push_back({y,x,z});
v.push_back({y,z,x});
v.push_back({z,x,y});
}
sort(v.begin(),v.end(),cmp);
memset(dp,0,sizeof dp);
int res=0;
for(int i=0;i<v.size();i++){
dp[i]=v[i].z;
for(int j=i-1;j>=0;j--)
if(v[j].x<v[i].x&&v[j].y<v[i].y){
dp[i]=max(dp[i],dp[j]+v[i].z);
}
res=max(res,dp[i]);
}
v.clear();
cout<<"Case "<<Case++<<": maximum height = ";
cout<<res<<endl;
}
return 0;
}