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
Case 1: maximum height = 40 Case 2: maximum height = 21 Case 3: maximum height = 28 Case 4: maximum height = 342
题目倒是不难!对于动态规划的题,我觉得最重要的就是找出所谓的递归方程吧!
这点最为重要!找到了递归方程,代码实现只是时间问题罢了!
这道题目有一些要点要抓住!
1,下一层的面积要严格大于上一层!我在这里错了几次!所谓严格大于,那就是下一层的长宽都大于下一层的长宽或宽长,等于都不行!
2,这道问题比较像01背包问题!我用的方法是拆分!即将一种block拆成3种!(一种block有三种摆放姿势,且一种block最多放这三种姿势)这样,先按照面积排序!然后再次动归!可以减少时间复杂度!
3,hdp[i]表示如果以第i块block为顶,最多可以达到的高度!
发AC代码吧!
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;
struct block{
int area;
int height;
int width;
int length;
};
bool cmp(block &a,block &b)
{
return a.area>b.area;
}
int main()
{
int kinds;
int i,j,l,w,h,s=1;
int max;
int k;
block b[100];
vector<int> hdp(300);
block temp;
while(1)
{
k=0;
cin>>kinds;
if(kinds==0) break;
for(i=0;i<kinds;i++)
{
cin>>l>>w>>h;
temp.width=l;temp.length=w;
temp.area=l*w; temp.height=h;
b[k++]=temp;
temp.width=l;temp.length=h;
temp.area=l*h; temp.height=w;
b[k++]=temp;
temp.width=h;temp.length=w;
temp.area=h*w; temp.height=l;
b[k++]=temp;
}
//会错意了!严格的小,那就是每一条边(长宽)都要比底下的小!还不能等于!
sort(b,b+kinds*3,cmp);//排序,按照面积从大到小排序!
hdp[0]=b[0].height;//如果以最大底面积的砖块为底,则最高的高度为它的高度
//接下来是动态规划了!
//动归方程为 hdp[i]=max{hdp[j]+b[i].height,b[i].height|b[j].area>b[i].area,j=0,1,……i-1};
for(i=1;i<kinds*3;i++)
{
hdp[i]=b[i].height;
for(j=0;j<i;j++)//如果面积大于b[i].area;那么一定不满足题意!
{
if( (b[i].width<b[j].width && b[i].length<b[j].length)||(b[i].width<b[j].length && b[i].length<b[j].width) )
if( hdp[j]+b[i].height>hdp[i])//寻找最大的值
hdp[i]=hdp[j]+b[i].height;
}
}
max=0;
for(i=0;i<kinds*3;i++)
if(hdp[i]>max)
max=hdp[i];
printf("Case %d: maximum height = %d\n",s,max);
s++;
}
return 0;
}