题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68966#problem/C
题意:给定一些长方体的尺寸,数量都是无限个,然后求这写长方体能堆切成的最大高度。PS:接触面的上面必须严格小于下面的面。
这题和紫书P269的巴比伦塔例题差不多,可以说是一模一样,紫书上把这种题型叫DAG上最长路。看了别人的代码AC的。
思路:把所有长方体的状态枚举出来,然后排序(假设为大边在前,小边在后),这样一来。用dp[i]表示以状态i结束的最大高度,这dp[i]只能由其前面的状态转移得到。所以枚举前面的状态,O(N^2)解决。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
int x,y,z;
bool operator<(const node &a)const{
if(x!=a.x) return x>a.x;
return y>a.y;
}
}S[200];
int N,tot,dp[200];
int main(){
//freopen("in.txt","r",stdin);
int kase=0;
while(cin>>N && N){
kase++;tot=0;
int a,b,c;
for(int i=0;i<N;i++){
scanf("%d %d %d",&a,&b,&c);//存储所有状态
S[tot++]=(node){a,b,c};if(a!=b) S[tot++]=(node){b,a,c};
S[tot++]=(node){a,c,b};if(a!=c) S[tot++]=(node){c,a,b};
S[tot++]=(node){b,c,a};if(b!=c) S[tot++]=(node){c,b,a};
}
sort(S,S+tot);//状态排序
memset(dp,0,sizeof(dp));
int ans=S[0].z;
for(int i=0;i<tot;i++){//枚举终点状态
dp[i]=S[i].z;
for(int j=0;j<i;j++)//枚举转移中介状态
if(S[j].x>S[i].x && S[j].y>S[i].y)
dp[i]=max(dp[i],dp[j]+S[i].z);
if(dp[i]>ans) ans=dp[i];
}
printf("Case %d: maximum height = %d\n",kase,ans);
}
return 0;
}