題目鏈接: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;
}