UVA 437 巴比伦塔
题目大意:
有n(n<=30) 种立方体,每种都有无穷多个。要求选一些立方体摞成一根尽量高的柱子(任意一条边都可以作为高),使得每个立方体的底面长宽分别严格小于它下方立方体的底面长宽。
DAG模型————无固定终点的最长路
详情请见算法竞赛入门经典(第二版) Page269
原创代码,三种情况分得很清楚。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,a[305],b[305],c[305];
int d[305][4];
int pan1(int i, int j){
if(b[i]<b[j] && c[i]<c[j]) return 1;
if(b[i]<c[j] && c[i]<b[j]) return 1;
return 0;
}
int pan2(int i, int j){
if(a[i]<b[j] && c[i]<c[j]) return 1;
if(a[i]<c[j] && c[i]<b[j]) return 1;
return 0;
}
int pan3(int i, int j){
//printf("ok");
if(a[i]<b[j] && b[i]<c[j]) return 1;
if(a[i]<c[j] && b[i]<b[j]) return 1;
return 0;
}
int pan4(int i, int j){
if(b[i]<a[j] && c[i]<c[j]) return 1;
if(b[i]<c[j] && c[i]<a[j]) return 1;
return 0;
}
int pan5(int i, int j){
if(b[i]<a[j] && c[i]<b[j]) return 1;
if(b[i]<b[j] && c[i]<a[j]) return 1;
//printf("pp");
return 0;
}
int pan6(int i, int j){
if(a[i]<a[j] && c[i]<c[j]) return 1;
if(a[i]<c[j] && c[i]<a[j]) return 1;
return 0;
}
int pan7(int i, int j){
if(a[i]<a[j] && c[i]<b[j]) return 1;
if(a[i]<b[j] && c[i]<a[j]) return 1;
return 0;
}
int pan8(int i, int j){
if(a[i]<a[j] && b[i]<c[j]) return 1;
if(a[i]<c[j] && b[i]<a[j]) return 1;
return 0;
}
int pan9(int i, int j){
if(a[i]<a[j] && b[i]<b[j]) return 1;
if(a[i]<b[j] && b[i]<a[j]) return 1;
return 0;
}
int dp(int i, int op){
if(op == 0){
if(d[i][op] != a[i]) return d[i][op];
//printf("kk");
for(int j=1;j<=n;j++){
if(pan1(i,j)) d[i][op] = max(d[i][op] , dp(j,0) + a[i]);// i bc; j bc
if(pan4(i,j)) d[i][op] = max(d[i][op] , dp(j,1) + a[i]);//i-->bc ; j-->ac
if(pan5(i,j)) d[i][op] = max(d[i][op] , dp(j,2) + a[i]);//i-->bc;j-->ab
}
}
if(op == 1){
if(d[i][op] != b[i]) return d[i][op];
for(int j=1;j<=n;j++){
if(pan2(i,j)) d[i][op] = max(d[i][op] , dp(j,0) + b[i]);//i ac ; j bc
if(pan6(i,j)) d[i][op] = max(d[i][op] , dp(j,1) + b[i]);//i-->ac ; j-->ac
if(pan7(i,j)) d[i][op] = max(d[i][op] , dp(j,2) + b[i]);//i-->ac;j-->ab
}
}
if(op == 2){
if(d[i][op] != c[i]) return d[i][op];
for(int j=1;j<=n;j++){
if(pan3(i,j)) d[i][op] = max(d[i][op] , dp(j,0) + c[i]);//i ab; j bc
if(pan8(i,j)) d[i][op] = max(d[i][op] , dp(j,1) + c[i]);//i-->ab ; j-->ac
if(pan9(i,j)) d[i][op] = max(d[i][op] , dp(j,2) + c[i]);//i-->ab;j-->ab
}
}
//printf("kk");
return d[i][op];
}
int main(){
int num=0;
while(scanf("%d",&n)){
num++;
if(n==0) break;
int ans=0;
for(int i=1;i<=n;i++){
scanf("%d%d%d",&a[i],&b[i],&c[i]);
}
for(int i=1;i<=n;i++){
d[i][0]=a[i];
d[i][1]=b[i];
d[i][2]=c[i];
}
for(int i=1;i<=n;i++){
//printf("%d ",dp(i,2));
ans = max(ans,max(max(dp(i,0),dp(i,1)),dp(i,2)));
}
printf("Case %d: maximum height = %d\n",num,ans);
}
return 0;
}