Description
Input
Output
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
网上题解:
题目倒是不难!对于动态规划的题,我觉得最重要的就是找出所谓的递归方程吧!
这点最为重要!找到了递归方程,代码实现只是时间问题罢了!
这道题目有一些要点要抓住!
1,下一层的面积要严格大于上一层!我在这里错了几次!所谓严格大于,那就是下一层的长宽都大于下一层的长宽或宽长,等于都不行!
2,这道问题比较像01背包问题!我用的方法是拆分!即将一种block拆成6种!
3.注意这里的最大值不一定是dp[n],需要选一下
做这道题的时候也算是曲折坎坷了,下面细细道来。。
其实之前都没怎么系统的做过关于DP的题目,所以借着之前的一点基础,看了两道DP的题型就开始YY敲代码了。。
我的dp[i]定义是在当前Block底面范围能放下的最高的高度,也就是说当前的这个Block是可以放,也可以不放的,所以我的状态转移方程也就成了dp[i]=max{ d[j...] , d[k...]+h }
这里的dp[j...]是指与i长宽一样所有的Block上能放下的高度(也就是不放当前Block),dp[k]是能在当前面积上放下的(长宽严格比当前长宽小的)高度(也就是放当前的Block)
但是开始的时候感觉不用旋转6种,只旋转了三种,在之后的判断中处理,但是却错了,原因是从小到大排序后,后面的可能能放在前面上面,如果是三种这样状态就少了,比如
3 5 7
6 4 9
所以不能旋转三种,并且按照长宽排序,如下的代码是错误的。。。
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-6 #define MAX 100005 #define INF 0x3f3f3f3f #define LL long long #define pii pair<int,int> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z) ///map<int,int>mmap; ///map<int,int >::iterator it; using namespace std; struct Rec{ int l; int w; int h; }rec[35*6]; bool cmp(Rec a,Rec b){ if(a.l!=b.l) return a.l<b.l; if(a.w!=b.w) return a.w<b.w; return a.h<b.h; ///£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡ //return a.l*a.w<b.l*b.w; } int dp[35*6]; int main() { int n; int xx=1; while(~rd(n)&&n) { int coun=1; for(int i=1;i<=n;i++){ scanf("%d%d%d",&rec[coun].l,&rec[coun].w,&rec[coun].h); coun++; rec[coun].l=rec[coun-1].l ,rec[coun].w=rec[coun-1].h ,rec[coun].h=rec[coun-1].w; coun++; rec[coun].l=rec[coun-2].w ,rec[coun].w=rec[coun-2].h ,rec[coun].h=rec[coun-2].l; coun++; } coun--; sort(rec+1,rec+coun+1,cmp); // for(int i=1;i<=coun;i++) // cout<<rec[i].l<<' '<<rec[i].w<<' '<<rec[i].h<<endl; int mmax=-INF; dp[0]=0; for(int i=1;i<=coun;i++){ int l=rec[i].l,w=rec[i].w,h=rec[i].h ; dp[i]=h; for(int j=i-1;j>0;j--) if( ( rec[j].l<l && rec[j].w<w )|| (rec[j].l<w && rec[j].w<l) ) dp[i]=max( dp[i] ,h+dp[j]); ///!!!!!!! int tempMax=-INF; for(int j=0;j<i;j++) if(rec[j].l==l && rec[j].w==w) tempMax=max(tempMax,dp[j]); dp[i]=max( tempMax , dp[i] ); mmax=max(dp[i],mmax); } // for(int i=1;i<=coun;i++) // cout<<dp[i]<<' '; // cout<<endl; printf("Case %d: maximum height = %d\n",xx++,mmax); } return 0; }
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-6 #define MAX 100005 #define INF 0x3f3f3f3f #define LL long long #define pii pair<int,int> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z) ///map<int,int>mmap; ///map<int,int >::iterator it; using namespace std; struct Rec{ int l; int w; int h; }rec[35*6]; bool cmp(Rec a,Rec b){ return a.l*a.w<b.l*b.w; } int dp[35*6]; int main() { int n; int xx=1; while(~rd(n)&&n) { int coun=1; for(int i=1;i<=n;i++){ scanf("%d%d%d",&rec[coun].l,&rec[coun].w,&rec[coun].h); coun++; rec[coun].l=rec[coun-1].l ,rec[coun].w=rec[coun-1].h ,rec[coun].h=rec[coun-1].w; coun++; rec[coun].l=rec[coun-2].w ,rec[coun].w=rec[coun-2].h ,rec[coun].h=rec[coun-2].l; coun++; } coun--; sort(rec+1,rec+coun+1,cmp); // for(int i=1;i<=coun;i++) // cout<<rec[i].l<<' '<<rec[i].w<<' '<<rec[i].h<<endl; int mmax=-INF; dp[0]=0; for(int i=1;i<=coun;i++){ int l=rec[i].l,w=rec[i].w,h=rec[i].h ; dp[i]=h; for(int j=i-1;j>0;j--) if( ( rec[j].l<l && rec[j].w<w )|| (rec[j].l<w && rec[j].w<l) ) dp[i]=max( dp[i] ,h+dp[j]); ///!!!!!!! int tempMax=-INF; for(int j=0;j<i;j++) if(rec[j].l==l && rec[j].w==w) tempMax=max(tempMax,dp[j]); dp[i]=max( tempMax , dp[i] ); mmax=max(dp[i],mmax); } // for(int i=1;i<=coun;i++) // cout<<dp[i]<<' '; // cout<<endl; printf("Case %d: maximum height = %d\n",xx++,mmax); } return 0; }
旋转六种的直接用上面的思路就完全可以了。。代码:
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-6 #define MAX 100005 #define INF 0x3f3f3f3f #define LL long long #define pii pair<int,int> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z) ///map<int,int>mmap; ///map<int,int >::iterator it; using namespace std; struct Rec{ int l; int w; int h; }rec[35*6]; bool cmp(Rec a,Rec b){ if(a.l!=b.l) return a.l<b.l; if(a.w!=b.w) return a.w<b.w; return a.h<b.h; ///£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡ } int dp[35*6]; int main() { int n; int xx=1; while(~rd(n)&&n) { int coun=1; for(int i=1;i<=n;i++){ scanf("%d%d%d",&rec[coun].l,&rec[coun].w,&rec[coun].h); coun++; ///×¢Ò⣡£¡£¡ rec[coun].l=rec[coun-1].l ,rec[coun].w=rec[coun-1].h ,rec[coun].h=rec[coun-1].w; coun++; rec[coun].l=rec[coun-2].w ,rec[coun].w=rec[coun-2].h ,rec[coun].h=rec[coun-2].l; coun++; rec[coun].l=rec[coun-3].w ,rec[coun].w=rec[coun-3].l ,rec[coun].h=rec[coun-3].h; coun++; rec[coun].l=rec[coun-4].h ,rec[coun].w=rec[coun-4].l ,rec[coun].h=rec[coun-4].w; coun++; rec[coun].l=rec[coun-5].h ,rec[coun].w=rec[coun-5].w ,rec[coun].h=rec[coun-5].l; coun++; } coun--; sort(rec+1,rec+coun+1,cmp); int mmax=-INF; dp[0]=0; for(int i=1;i<=coun;i++){ int l=rec[i].l,w=rec[i].w,h=rec[i].h ; dp[i]=h; for(int j=i-1;j>0;j--) if( ( rec[j].l<l && rec[j].w<w ) ) dp[i]=max( dp[i] ,h+dp[j]); ///!!!!!!! int tempMax=-INF; for(int j=0;j<i;j++) if(rec[j].l==l && rec[j].w==w) tempMax=max(tempMax,dp[j]); dp[i]=max( tempMax , dp[i] ); mmax=max(dp[i],mmax); } printf("Case %d: maximum height = %d\n",xx++,mmax); } return 0; }
其实网上盛传的比较多的一种版本是下面的这种,这里的dp[i]指的是放在当前Block上的最大高度,和上面的一种区别是当前的这个Block一定是放在最下面的。
代码:
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-6 #define MAX 100005 #define INF 0x3f3f3f3f #define LL long long #define pii pair<int,int> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z) ///map<int,int>mmap; ///map<int,int >::iterator it; using namespace std; struct Rec{ int l; int w; int h; }rec[35*6]; bool cmp(Rec a,Rec b){ if(a.l!=b.l) return a.l<b.l; if(a.w!=b.w) return a.w<b.w; return a.h<b.h; ///£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡£¡ } int dp[35*6]; int main() { int n; int xx=1; while(~rd(n)&&n) { int coun=1; for(int i=1;i<=n;i++){ scanf("%d%d%d",&rec[coun].l,&rec[coun].w,&rec[coun].h); coun++; ///×¢Ò⣡£¡£¡ rec[coun].l=rec[coun-1].l ,rec[coun].w=rec[coun-1].h ,rec[coun].h=rec[coun-1].w; coun++; rec[coun].l=rec[coun-2].w ,rec[coun].w=rec[coun-2].h ,rec[coun].h=rec[coun-2].l; coun++; rec[coun].l=rec[coun-3].w ,rec[coun].w=rec[coun-3].l ,rec[coun].h=rec[coun-3].h; coun++; rec[coun].l=rec[coun-4].h ,rec[coun].w=rec[coun-4].l ,rec[coun].h=rec[coun-4].w; coun++; rec[coun].l=rec[coun-5].h ,rec[coun].w=rec[coun-5].w ,rec[coun].h=rec[coun-5].l; coun++; } coun--; sort(rec+1,rec+coun+1,cmp); int mmax=-INF; for(int i=1;i<=coun;i++){ int l=rec[i].l,w=rec[i].w,h=rec[i].h ; dp[i]=h; for(int j=i-1;j>0;j--) if( rec[j].l<l && rec[j].w<w ) dp[i]= max(dp[i],h+dp[j] ); if(mmax<dp[i]) mmax=dp[i]; } printf("Case %d: maximum height = %d\n",xx++,mmax); } return 0; }