还是蛮简单的(因为数据不是怎么大),但今天是颓废的一天~【滑稽】【逃
是中山纪念中学的题。。。题目链接戳
Leo是一个快乐的火星人,总是能和地球上的OIers玩得很high。
2012到了,Leo又被召回火星了,在火星上没人陪他玩了,但是他有好多好多积木,于是他开始搭积木玩。
火星人能制造n种积木,积木能无限供应。每种积木都是长方体,第i种积木的长、宽、高分别为li、wi、hi。积木可以旋转,使得长宽高任意变换。Leo想要用这些积木搭一个最高的塔。问题是,如果要把一个积木放在另一个积木上面,必须保证上面积木的长和宽都严格小于下面积木的长和宽。这意味着,即使两块长宽相同的积木也不能堆起来。
火星上没有电脑,好心的你决定帮助Leo求出最高的塔的高度。
【提示】
每种积木都可以拆分成高度分别为li、wi、hi的三种积木,另两边作为长和宽,保证长>=宽。
Input-
第一行,一个整数n,表示积木的种数
接下来n行,每行3个整数li,wi,hi,表示积木的长宽高
Output-
一行一个整数,表示塔高的最大值
Sample Input-
-Sample Input1:
1
10 20 30
-Sample Input2:
2
6 8 10
5 5 5
-Sample Input3:
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27
Sample Output-
-Sample Output1:
40
-Sample Output2:
21
-Sample Output3:
342
- 由于我们可以把积木旋转摆放,所以每种积木我们都可以获得3种不同的形态。
(长宽高全排列6种,因为长必须比宽高,所以变成3种) - 我们按长从大到小排序(如果长相同按宽从大到小排序),使后面可以放到前面的上。
(形成一个不下降子序列) - 然后DP.
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,ans[100001],Ans,a,b,c;
struct asdf{
int C,K,G; //这是长,这是宽,这是高............的首拼音
} s[100001];
bool cmp(asdf aa,asdf bb){ //按长从大到小排
if(aa.C != bb.C) return aa.C > bb.C; //如果长度不相同
return aa.K > bb.K; //长度相同按宽从大到小排
}
int main(){
freopen("brick.in","r",stdin);
freopen("brick.out","w",stdout);
scanf("%d",&n); //读入,没问题
for(int i = 1; i <= n; ++i){
scanf("%d%d%d",&a,&b,&c);
s[i * 3 - 2] = (asdf) {max(a,b), min(a,b), c}; //将3种情况存到结构体里
s[i * 3 - 1] = (asdf) {max(a,c), min(a,c), b};
s[i * 3 - 0] = (asdf) {max(b,c), min(b,c), a};
}
sort(s + 1, s + 1 + 3 * n, cmp); //排序,如上所说
for(int i = 1; i <= 3 * n; ++i){ //每种积木轮一遍
for(int j = i - 1; j >= 0; --j) //可能堆到的
if(s[i].C < s[j].C && s[i].K < s[j].K) //如果摆得上去
ans[i] = max(ans[i],ans[j]); //取一个最大值
ans[i] += s[i].G; //加上本积木的最大值
Ans = max(Ans,ans[i]); //Ans存一下
}
printf("%d",Ans); //输出
fclose(stdin);
fclose(stdout);
}