思路:放代码上了
代码如下:
/*
最优解是max height
最优子结构是以i方块作为最后一块的最大长度
子问题的最优解是以前1,2,3...i-1个方块作为最后一块的最大长度
显然:最优子结构包含了子问题的最优解
并且这些子问题的解之间相互独立(其中一个问题的解,不会影响另外一个)
重叠子问题:每次都不用再计算子问题的解,因为这些解都已经保存在了表中
综上:用dp[i]保存以i方块作为最后一块的最大长度,dp[i]=dp[k](k=1...n && block[i]>block[k]);
ans=max(dp[1...n]);
复杂度(O(n^2)) ;
这题的坑点。。。别的想法都没错,只有一个地方错了,如果是无序的(后面的可能可以放到前面的顶上)
就说明子问题的最优解不是以前1,2,3...i-1个方块作为最后一块的最大长度而是1...n,但是因为是无序的所以
i..n作为最后一块的长度是不可知的,所以会导致错误
如果先按照面积排序,那么后面的方块,就不能放到前面的顶上了
子问题的最优解是以前1,2,3...i-1个方块作为最后一块的最大长度
如果是用记忆化搜索就不存在这个问题,因为每次调用的值,一定是确定的以i结尾的最大高度
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[200];
struct node
{
int x,y,z;
}block[200];
bool cmp(node a,node b)
{
return a.x * a.y<b.x * b.y;
}
int n;
int main()
{
int Case=1;
while(scanf("%d",&n),n)
{
int num=1;
while(n--)
{
int temp[3];
for(int i=0;i<3;i++)
{
scanf("%d",&temp[i]);
}
sort(temp,temp+3);
do
{
block[num].x=temp[0];
block[num].y=temp[1];
block[num++].z=temp[2];
}while(next_permutation(temp,temp+3));
}
sort(block+1,block+num+1,cmp);
int maxx=0;
for(int i=1;i<num;i++)
{
dp[i]=block[i].z;
for(int j=1;j<num;j++)
{
if(block[i].x>block[j].x && block[i].y>block[j].y)
{
dp[i]=max(dp[j]+block[i].z,dp[i]);
}
}
maxx=max(dp[i],maxx);
}
printf("Case %d: maximum height = %d\n",Case++,maxx);
}
return 0;
}
版权声明:本文为qq_39562952原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。