UVA 437 "The Tower of Babylon" (DAG上的动态规划)
题意
有 n 种立方体,每种都有无穷多个。
要求选一些立方体摞成一根尽量高的柱子(在摞的时候可以自行选择哪一条边作为高);
立方体 a 可以放在立方体 b 上方的前提条件是立方体 a 的底面长宽分别严格小于立方体 b 的底面长宽;
求最大高度;
思路
对于立方体 a(x,y,z)((长,宽,高)),因为每个立方体都有无穷个,所以 a 要拆成三个;
a1(x,y,z) , a2(x,z,y) , a3(y,z,x) 即分别以 z,y,x 作为高;
对于任意两个立方体 a,b ,如果 b 可以放在 a 的上方,那么连一条边 a->b,意思是 a 的上方可以放 b;
预处理出所有的点,以此构图,然后求出高最大的那条路经的高,输出即可;
AC代码
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define mem(a,b) memset(a,b,sizeof(a)) 5 const int maxn=100; 6 7 int n; 8 int num; 9 int head[maxn]; 10 struct Edge 11 { 12 int to; 13 int next; 14 }G[maxn*maxn]; 15 void addEdge(int u,int v) 16 { 17 G[num]={v,head[u]}; 18 head[u]=num++; 19 } 20 struct Date 21 { 22 int x,y; 23 }_date[maxn]; 24 ll h[maxn]; 25 ll dp[maxn];///dp[i]:以立方体i为最底层的立方体可以形成的最大高度 26 27 ll F(int u) 28 { 29 ll &ans=dp[u]; 30 if(ans != -1) 31 return ans; 32 ans=h[u]; 33 for(int i=head[u];~i;i=G[i].next) 34 { 35 int v=G[i].to; 36 ans=max(ans,F(v)+h[u]); 37 } 38 return ans; 39 } 40 bool isSat(int i,int j) 41 { 42 return _date[i].x > _date[j].x && _date[i].y > _date[j].y || 43 _date[i].x > _date[j].y && _date[i].y > _date[j].x ? true:false; 44 } 45 ll Solve() 46 { 47 ///最多可能加入(3*n)^2条边 48 ///G数组不要开小了 49 for(int i=1;i <= 3*n;++i) 50 for(int j=1;j <= 3*n;++j) 51 if(isSat(i,j))///判断立方体j是否可以放在立方体i上 52 addEdge(i,j); 53 mem(dp,-1); 54 for(int i=1;i <= 3*n;++i)///以i作为底层的立方体 55 dp[i]=F(i); 56 57 return *max_element(dp+1,dp+3*n+1); 58 } 59 void Init() 60 { 61 num=0; 62 mem(head,-1); 63 } 64 int main() 65 { 66 int kase=0; 67 while(~scanf("%d",&n) && n) 68 { 69 Init(); 70 for(int i=1;i <= n;++i) 71 { 72 int x,y,z; 73 scanf("%d%d%d",&x,&y,&z); 74 75 ///第i个立方体变为三个编号为i*3,i*3-1,i*3-2的立方体 76 int cnt=i*3; 77 _date[cnt]={x,y}; 78 h[cnt--]=z; 79 80 _date[cnt]={x,z}; 81 h[cnt--]=y; 82 83 _date[cnt]={y,z}; 84 h[cnt--]=x; 85 } 86 printf("Case %d: maximum height = %lld\n",++kase,Solve()); 87 } 88 return 0; 89 }