题目链接:点击打开链接
题意:
有n(n<=30)种立方体,每种都有无穷多个。要求选一些立方体摞成一根尽量高的柱子(可以自行选择哪一条边作为高),使得每个立方体的底面长宽分别严格小于它下方立方体的底面长宽。
思路:
由于每种立方体有无穷多个,而每个立方体有三种不同的面,那么就可以将问题抽象为最多有多少个长宽严格递减的面,很容易想到每个面最多摞一次。这道题很容易想成贪心,其实这是一道求最长递增子序列的问题。
首先生成面,需要先对录入的三个数进行排序,然后按照长>宽的规则生成3个面,然后对面进行排序。自定义比较函数时不能用a.length<b.length && a.width<b.width的规则排,因为这样会有一些面无法准确比较,就会产生乱序。需要按照面积进行排序,这样就能保证长宽较大的一定出现在较小的后面。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,dp[100];
struct node
{
int w,l,h;
bool operator <(node a)const
{
return w<a.w && l<a.l;
}
}p[100];
bool cmp(node a,node b)
{
return a.w*a.l<b.w*b.l;
}
int main()
{
int cas=0;
while(scanf("%d",&n) && n)
{
int sq[3],cnt=0;
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&sq[0],&sq[1],&sq[2]);
sort(sq,sq+3);
p[cnt].h=sq[2];
p[cnt].w=sq[0];
p[cnt++].l=sq[1];
p[cnt].h=sq[1];
p[cnt].w=sq[0];
p[cnt++].l=sq[2];
p[cnt].h=sq[0];
p[cnt].w=sq[1];
p[cnt++].l=sq[2];
}
sort(p,p+cnt,cmp);
for(int i=0;i<cnt;i++)
{
dp[i]=p[i].h;
for(int j=0;j<i;j++)
{
if(p[j]<p[i])
dp[i]=max(dp[i],dp[j]+p[i].h);
}
}
int ans=0;
for(int i=0;i<cnt;i++)
ans=max(ans,dp[i]);
printf("Case %d: maximum height = %d\n",++cas,ans);
}
return 0;
}