题目
题目粘贴格式有问题,请自行点击
题目大意
有N种长方体,每种无限个,从其中选出一些叠成一根柱子(长方体可以旋转),使得上面的长方体的长和宽严格小于下面长方体的长和宽,求柱子的最大高度。
思路
“上面的严格小于下面的”,看到这种题,瞬间想到了最长上升子序列。
只是条件从1个变为了2个,多了“长方体无限多”的条件而已。
首先解决第一个:长和宽都要严格小于前面的。这还用解决吗……if里面多加一个条件就好了。或者你装逼可以重载运算符。
第二个,仔细想想,1个长方体最多能用3次,为什么?假设这个长方体的长宽高分别为a,b,c,那么这个长方体的底面只有可能是:a*b,b*c,a*c三种。假如下面一个长方体的底面为a*b,上面的长方体最多只能选b*c或a*c,如果上面的长方体的底面也为a*b,就不满足“严格小于”的条件了。如果中间又隔了几个长方体,就更不可能是a*b了,所以一个长方体以a*b,b*c,a*c各作底面一次,也就只能用3次了。
也就是说,存的时候每个长方体存3次,分别以长,宽,高为高。
DP前先按底面排个序,然后和最长上升子序列做法一模一样。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
#define MAXN 30
#define INF 0x7fffffff
struct Cube
{
int size[3];//存长,宽,高
}c[MAXN*3+5];//注意开3倍空间(话说我之前没开3倍也AC了,数据是有多水……)
int N;
int f[MAXN*3+5];
bool cmp(Cube x,Cube y)//按底面(先长后宽)排序
{
if(x.size[0]!=y.size[0]) return x.size[0]<y.size[0];
return x.size[1]<y.size[1];
}
int DP(int n)
{
int ans=-1;
for(int i=1;i<=n;i++)
{
f[i]=c[i].size[2];
for(int j=1;j<=i;j++)
if(c[j].size[0]<c[i].size[0]&&c[j].size[1]<c[i].size[1]&&f[i]<f[j]+c[i].size[2])//和最长上升子序列几乎相同,只是最长上升子序列每次加1,这个每次加上长方体的高
f[i]=f[j]+c[i].size[2];
ans=max(ans,f[i]);
}
return ans;
}
int main()
{
int cas=0;
while(1)
{
N=read();
if(!N) return 0;
int tN=0;
for(int i=1;i<=N;i++)
{
int x=read(),y=read(),z=read();
c[++tN].size[0]=max(x,y);c[tN].size[1]=min(x,y);c[tN].size[2]=z;
c[++tN].size[0]=max(y,z);c[tN].size[1]=min(y,z);c[tN].size[2]=x;
c[++tN].size[0]=max(x,z);c[tN].size[1]=min(x,z);c[tN].size[2]=y;//存3次,保证长>=宽
}
sort(c+1,c+tN+1,cmp);//排序
printf("Case %d: maximum height = %d\n",++cas,DP(tN));
}
}

本文探讨了一个经典的长方体重叠问题,通过分析长方体摆放方式及运用最长上升子序列算法来求解堆叠柱子的最大高度。
932

被折叠的 条评论
为什么被折叠?



