【DP】Leo搭積木

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章