A group of researchers are designing an experiment to test the IQ of a monkey. They will hang a banana at the roof of a building, and at the mean time, provide the monkey with some blocks. If the monkey is clever enough, it shall be able to reach the banana by placing one block on the top another to build a tower and climb up to get its favorite food.
The researchers have n types of blocks, and an unlimited supply of blocks of each type. Each type-i block was a rectangular solid with linear dimensions (xi, yi, zi). A block could be reoriented so that any two of its three dimensions determined the dimensions of the base and the other dimension was the height.
They want to make sure that the tallest tower possible by stacking blocks can reach the roof. The problem is that, in building a tower, one block could only be placed on top of another block as long as the two base dimensions of the upper block were both strictly smaller than the corresponding base dimensions of the lower block because there has to be some space for the monkey to step on. This meant, for example, that blocks oriented to have equal-sized bases couldn't be stacked.
Your job is to write a program that determines the height of the tallest tower the monkey can build with a given set of blocks.
Input
The input file will contain one or more test cases. The first line of each test case contains an integer n,
representing the number of different blocks in the following data set. The maximum value for n is 30.
Each of the next n lines contains three integers representing the values xi, yi and zi.
Input is terminated by a value of zero (0) for n.
Output
For each test case, print one line containing the case number (they are numbered sequentially starting from 1) and the height of the tallest possible tower in the format "Case case: maximum height = height".
Sample Input
1 10 20 30 2 6 8 10 5 5 5 7 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 5 31 41 59 26 53 58 97 93 23 84 62 64 33 83 27 0
Sample Output
Case 1: maximum height = 40 Case 2: maximum height = 21 Case 3: maximum height = 28 Case 4: maximum height = 342
Topic: Give you n cuboids and their lengths, widths and heights. These cuboids are infinite in number and can be rotated arbitrarily. Cuboids can be stacked on cuboids larger in length and width (not all equal). Ask how high the highest can be stacked.
thinking
(1) Input problem; this is not an ordinary input, because a cube can be used many times.
But in fact, it can be repeated three times or two times at most. (Actually, I wrote two more at the beginning, because I think it is wrong to think that the maximum and minimum sides of a rectangle can be used, while the other side and the maximum side are equal, and the minimum side is equal.)
(2) Such a cuboid becomes three cuboids and chooses the cuboid to make it the highest. At first glance, it looks like a backpack, an item to choose or not to choose. But naively, I forget that there is no order in choosing items for backpack. This item can be placed in the final judgement, or in front of it. But this question is different. First choosing and then choosing are different. First choosing may not be able to choose. But the latter may or may not be chosen. This difference leads to different ideas.
(3) Since we want to get the maximum, it's better to put the maximum behind, so that we can start looking for it from the beginning (do you think of greed), but greed can't do this problem well?
If you encounter the same length (or width), which one would you choose? And even if you choose the highest one (assuming the first one, not the second one), you can guarantee that the next one will not be wider (or longer) than the first one, shorter than the second one, and higher than the second one; then you can only plan dynamically, and dynamic programming will record the best solution of all the previous situations, using the first one to push the next one, greed can only use the nearest one. Push one down
This is the essential difference between action and greed.
This is my way of thinking. Write it out for you to think about.
Here is the idea of the question.
(1) First input, then change one to six, then arrange the order, from big to small (so convenient)
(2) Then the longest monotone descending subsequence
So why is it associated with the longest monotonic descending subsequence?
Yes, after we sort the cubes, they are arranged from small to large. We want to find the highest, so in fact, we are replacing the most monotonic descending subsequences with the highest.
Let's look at the dynamics of the longest monotonic descending subsequence
In fact, it's a simple sentence.
Traverse from the beginning, every time, to find the front, whether there is greater than this, if there is, then find the largest result (that is, the best solution) to this state, add the current value on this state, is the current best solution;
C++ version 1
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int t; int n,ant; int maxh; int x,y,z; struct shape{ int l,w,h; }a[200]; bool cmp(shape a,shape b) { if (a.l == b.l) return a.w > b.w; return a.l > b.l; } void PushUp(int t1,int t2,int t3) { a[ant].h = t3; a[ant].l = t1; a[ant].w = t2; ant++; a[ant].h = t3; a[ant].l = t2; a[ant].w = t1; ant++; a[ant].h = t2; a[ant].l = t1; a[ant].w = t3; ant++; a[ant].h = t2; a[ant].l = t3; a[ant].w = t1; ant++; a[ant].h = t1; a[ant].l = t2; a[ant].w = t3; ant++; a[ant].h = t1; a[ant].l = t3; a[ant].w = t2; ant++; } int main() { t=0; while(scanf("%d",&n)!=EOF){ if(n==0) break; t++; maxh=0; ant=1; for(int i=1;i<=n;i++){ scanf("%d%d%d",&x,&y,&z); PushUp(x,y,z); } sort(a+1,a+6*n+1,cmp); int dp[200]; int ans=0; for(int i=1;i<=6*n;i++){ dp[i]=a[i].h; for(int j=i-1;j>=0;j--){ if(a[i].l<a[j].l&&a[i].w<a[j].w){ dp[i]=max(dp[i],dp[j]+a[i].h); } } ans=max(dp[i],ans); } printf("Case %d: maximum height = %d\n",t,ans); } //cout << "Hello world!" << endl; return 0; }
C++ version two
/* HDU1069Monkey and Banana Title: Give some cuboids and let you pile them into towers. The tower below is required to be larger (longer and wider) than the tower above. And the number of each cuboid is infinite. This topic examines the longest ordered subsequence in dynamic programming. */ #include<stdio.h> #include<algorithm> const int MAXN=200; using namespace std; struct Block { int x,y,high; int dp;//The maximum height of the box at the bottom }b[MAXN]; bool cmp(Block a,Block b)//Sort by sort function, first by x and then by y { if(a.x<b.x) return 1; else if(a.x==b.x&&a.y<b.y) return 1; else return 0; } int main() { int n,i,x,y,z,j,k; int iCase=0; while(scanf("%d",&n),n) { iCase++; k=0; while(n--) { scanf("%d%d%d",&x,&y,&z); //Put all the possibilities of putting the given block in block [] so that the problem of infinite blocks can be solved. if(x==y) { if(y==z)//Three equals, one is enough. { b[k].x=x;b[k].y=y;b[k].high=z;b[k].dp=b[k].high;k++; } else //Three Radiation Methods for x==y!=z { b[k].x=x;b[k].y=y;b[k].high=z;b[k].dp=b[k].high;k++; b[k].x=z;b[k].y=y;b[k].high=x;b[k].dp=b[k].high;k++; b[k].x=y;b[k].y=z;b[k].high=x;b[k].dp=b[k].high;k++; } } else { if(y==z)//Three ways of releasing { b[k].x=x;b[k].y=y;b[k].high=z;b[k].dp=b[k].high;k++; b[k].x=y;b[k].y=x;b[k].high=z;b[k].dp=b[k].high;k++; b[k].x=y;b[k].y=z;b[k].high=x;b[k].dp=b[k].high;k++; } else if(x==z) { b[k].x=x;b[k].y=y;b[k].high=z;b[k].dp=b[k].high;k++; b[k].x=y;b[k].y=x;b[k].high=z;b[k].dp=b[k].high;k++; b[k].x=x;b[k].y=z;b[k].high=y;b[k].dp=b[k].high;k++; } else//Three unequal and six methods of releasing { b[k].x=x;b[k].y=y;b[k].high=z;b[k].dp=b[k].high;k++; b[k].x=y;b[k].y=x;b[k].high=z;b[k].dp=b[k].high;k++; b[k].x=x;b[k].y=z;b[k].high=y;b[k].dp=b[k].high;k++; b[k].x=z;b[k].y=x;b[k].high=y;b[k].dp=b[k].high;k++; b[k].x=y;b[k].y=z;b[k].high=x;b[k].dp=b[k].high;k++; b[k].x=z;b[k].y=y;b[k].high=x;b[k].dp=b[k].high;k++; } } } sort(b,b+k,cmp); int maxh=0; for(i=1;i<k;i++) { for(j=0;j<i;j++) if(b[i].x>b[j].x&&b[i].y>b[j].y) b[i].dp=max(b[j].dp+b[i].high,b[i].dp); if(b[i].dp>maxh)maxh=b[i].dp; } printf("Case %d: maximum height = %d\n",iCase,maxh); } return 0; }
C++ version three
#include<cstdio> #include<algorithm> using namespace std; struct stu { int l,w,h; }st[185]; bool cmp(stu a,stu b) //Judging from top to bottom, so sort from small to large { if(a.l != b.l) return a.l < b.l; else return a.w < b.w; } int main() { int k=1; int dp[185]; //dp[i] denotes the height from the top to the first block int n,a,b,c,max0,num; while(scanf("%d",&n) && n) { int i,j; num=0; for(i = 1 ; i <= n ; i++) { scanf("%d %d %d",&a,&b,&c); st[num].l=a,st[num].w=b,st[num++].h=c; //Each block has three layouts. st[num].l=a,st[num].w=c,st[num++].h=b; st[num].l=b,st[num].w=a,st[num++].h=c; st[num].l=b,st[num].w=c,st[num++].h=a; st[num].l=c,st[num].w=a,st[num++].h=b; st[num].l=c,st[num].w=b,st[num++].h=a; } sort(st,st+num,cmp); for(i = 0 ; i < num ; i++) { dp[i]=st[i].h; } for(i = 0 ; i < num ; i++) { for(j = 0 ; j < i ; j++) { if(st[j].l < st[i].l && st[j].w < st[i].w && dp[j]+st[i].h > dp[i]) { dp[i]=dp[j]+st[i].h; } } } sort(dp,dp+num); printf("Case %d: maximum height = ",k++); printf("%d\n",dp[num-1]); } return 0; }
C++ version four
#include <stdio.h> #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) typedef pair<int,int> pii; typedef long long LL; const double PI=acos(-1.0); const int N=190; struct info { int x; int y; int z; bool operator<(const info &t)const { if(x!=t.x) return x<t.x; return y<t.y; } info(int xx,int yy,int zz):x(xx),y(yy),z(zz){} info(){} }; vector<info>arr; int dp[N]; int main(void) { int n,i,j,x,y,z; int q=1; while (~scanf("%d",&n)&&n) { CLR(dp,0); arr.clear(); for (i=0; i<n; ++i) { scanf("%d%d%d",&x,&y,&z); arr.push_back(info(x,y,z)); arr.push_back(info(x,z,y)); arr.push_back(info(y,x,z)); arr.push_back(info(y,z,x)); arr.push_back(info(z,x,y)); arr.push_back(info(z,y,x)); } sort(arr.begin(),arr.end()); int SZ=arr.size(); for (i=0; i<SZ; ++i) { int pre_max=0; for (j=0; j<i; ++j) { if(arr[j].x<arr[i].x&&arr[j].y<arr[i].y&&dp[j]>pre_max) pre_max=dp[j]; } dp[i]=pre_max+arr[i].z; } printf("Case %d: maximum height = %d\n",q++,*max_element(dp,dp+SZ));//The n^2 algorithm here takes max, which is confused with the last direct output leading to WA. } return 0; }