題目大意是根據所給的有無限多個的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
所以在塔上面的立方體的底面積一定比下面的小。