Leo搭积木
题目
Leo是一个快乐的火星人,总是能和地球上的OIers玩得很high。
2012到了,Leo又被召回火星了,在火星上没人陪他玩了,但是他有好多好多积木,于是他开始搭积木玩。
火星人能制造n种积木,积木能无限供应。每种积木都是长方体,第i种积木的长、宽、高分别为li、wi、hi。积木可以旋转,使得长宽高任意变换。Leo想要用这些积木搭一个最高的塔。问题是,如果要把一个积木放在另一个积木上面,必须保证上面积木的长和宽都严格小于下面积木的长和宽。这意味着,即使两块长宽相同的积木也不能堆起来。
火星上没有电脑,好心的你决定帮助Leo求出最高的塔的高度。
【提示】
每种积木都可以拆分成高度分别为li、wi、hi的三种积木,另两边作为长和宽,保证长>=宽。
输入
第一行,一个整数n,表示积木的种数
接下来n行,每行3个整数li,wi,hi,表示积木的长宽高
输出
一行一个整数,表示塔高的最大值
输入样例
#1
1
10 20 30
#2
2
6 8 10
5 5 5
#3
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27
输出样例
#1
40
#2
21
#3
3420
数据范围
对于30%的数据 n<=8
对于100%的数据 n<=3000,最后答案不会超过32位整型
解题思路
其实这道题就是一道DP,
程序如下
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,x,y,z,a[100001],k,ans;
struct node
{
int c,k,g;
}f[100001];
bool cmp(node xx,node yy)
{
return xx.k < yy.k;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n; ++i)
{
scanf("%d%d%d",&x,&y,&z);
if(x >= y) f[++k] = (node){x,y,z}; //把每一种情况给存入数组
if(x >= z) f[++k] = (node){x,z,y};
if(y >= x) f[++k] = (node){y,x,z};
if(y >= z) f[++k] = (node){y,z,x};
if(z >= x) f[++k] = (node){z,x,y};
if(z >= y) f[++k] = (node){z,y,x};
}
sort(f + 1,f + 1 + k,cmp);
for(int i = 1;i <= k; ++i)
a[i] = f[i].g;
for(int i = k;i >= 1; --i)
{
for(int j = i + 1;j <= k; ++j)
{
if(f[i].c < f[j].c && f[i].k != f[j].k)//判断是否为最优的
a[i] = max(a[j] + f[i].g,a[i]);
}
}
for(int i = 1;i <= k; ++i)
ans = max(ans,a[i]);
printf("%d",ans);
return 0;
}