UVA 437 The Tower of Babylon(DAG上的動態規劃)

deepwzh發表於2017-02-09

題目大意是根據所給的有無限多個的n種立方體,求其所堆砌成的塔最大高度。

方法1,建圖求解,可以把問題轉化成求DAG上的最長路問題

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <vector>
 6 using namespace std;
 7 const int maxn = 31;
 8 struct Node{
 9     int x;
10     int y;
11     int z;
12     Node(int x,int y,int z):x(x),y(y),z(z){}
13     Node(){}
14     bool operator < (const Node &n)const{
15         return (x < n.x&& y < n.y) || (x < n.y&& y < n.x); 
16     }
17 };
18 vector<Node> vec;
19 int n;
20 int d[maxn*3];
21 int G[maxn*3][maxn*3];
22 int dp(int i,int h){
23     int & ans = d[i]; 
24     if(ans>0)return ans;
25     ans = h;
26     for(int j = 0; j < n*3; j++)if(G[i][j]){
27         ans = max(ans,dp(j,vec[j].z)+h);
28     }
29     return ans;
30 }
31 int main(){
32     int cnt = 0;
33     while(scanf("%d",&n)==1&&n){
34         vec.clear();
35         memset(G,0,sizeof(G));
36         memset(d,0,sizeof(d));
37         for(int i = 0; i< n; i++){
38             int x,y,z;
39             scanf("%d%d%d",&x,&y,&z);
40             vec.push_back(Node(x,y,z));
41             vec.push_back(Node(x,z,y));
42             vec.push_back(Node(z,y,x));
43         }
44         sort(vec.begin(),vec.end());
45 
46         for(int i = 0;i < n*3; i++){
47             for(int j = 0; j < n*3; j++){
48                 if(vec[i] < vec[j])
49                     G[i][j] = 1;
50             }
51         }
52         int result = -1;
53         for(int i = 0; i < n*3 ;i++){
54             result = max(result,dp(i,vec[i].z));
55         }
56         printf("Case %d: maximum height = %d\n",++cnt,result);
57     }
58     return 0;
59 }

 

方法2,轉化成最長遞增子序列問題求解

 

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <vector>
 6 using namespace std;
 7 const int maxn = 31;
 8 struct Node{
 9     int x;
10     int y;
11     int z;
12     Node(int x,int y,int z):x(x),y(y),z(z){}
13     Node(){}
14     bool operator < (const Node &n)const{
15         return (x < n.x&& y < n.y) || (x < n.y&& y < n.x); 
16     }
17 };
18 bool cmp(Node a,Node b){
19     return a.x*a.y < b.x*b.y;
20 }
21 vector<Node> vec;
22 int n;
23 int d[maxn*3];
24 int LIS(int n){
25     //d[i] = max{hi,d[j]}i>j ,A[i]>A[j]
26     int t = 0;
27     for(int i = 0; i < n*3; i++){
28         d[i] = vec[i].z;
29         for(int j = 0; j < i; j++)
30             if(vec[j] < vec[i])
31                 d[i] = max(d[i],d[j]+vec[i].z);
32         if(d[i] > t) t = d[i];
33     }
34     return t;
35 }
36 int main(){
37     int cnt = 0;
38     while(scanf("%d",&n)==1&&n){
39         vec.clear();
40         memset(d,0,sizeof(d));
41         for(int i = 0; i< n; i++){
42             int x,y,z;
43             scanf("%d%d%d",&x,&y,&z);
44             vec.push_back(Node(x,y,z));
45             vec.push_back(Node(x,z,y));
46             vec.push_back(Node(z,y,x));
47         }
48         sort(vec.begin(),vec.end(),cmp);
49         printf("Case %d: maximum height = %d\n",++cnt,LIS(n));
50     }
51     return 0;
52 }

 方法二要注意一點,我sort序列的時候用了一個cmp函式,他是根據立方體的底面積對立方體進行排序的。為什麼不採用和方法一一樣的排序方式呢?

因為a.x <b.x&&a.y<b.y

     或 a.y<b.x&&a.x<b.y

       =>Sa <Sb

所以在塔上面的立方體的底面積一定比下面的小。

相關文章