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;
}