>Description
有n种积木,积木能无限供应。每种积木都是长方体,第i种积木的长、宽、高分别为li、wi、hi。积木可以旋转,使得长宽高任意变换。Leo想要用这些积木搭一个最高的塔。问题是,如果要把一个积木放在另一个积木上面,必须保证上面积木的长和宽都严格小于下面积木的长和宽。这意味着,即使两块长宽相同的积木也不能堆起来。
给出积木,求最高能达到多少。
>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
对于30%的数据 n<=8
对于100%的数据 n<=3000,最后答案不会超过32位整型
>解题思路
我傻了这明明是一道简单DP我竟然比赛时没做出来
因为长方体可以旋转,所以一个长方体有三种方式摆放(要维护长长于宽)
求最长不下降序列的模板,首先得根据长从大到小排列所有的长方体,所有的表示选第个长方体的最高高度,每次计算时直接枚举 ~ 之间的长方体,如果可以放上去的话就计算
状态转移方程:
>代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
struct brick
{
int l, w, h;
}a[9010];
int n, t, ans, f[9010];
bool cmp (brick aa, brick bb) {return aa.l > bb.l;}
int main()
{
scanf ("%d", &n);
for (int i = 1; i <= n; i++)
{
t++;
scanf ("%d%d%d", &a[t].l, &a[t].w, &a[t].h);
a[++t] = (brick) {a[t - 1].l, a[t - 1].h, a[t - 1].w};
a[++t] = (brick) {a[t - 2].w, a[t - 2].h, a[t - 2].l};
}
for (int i = 1; i <= t; i++)
if (a[i].l < a[i].w) swap (a[i].l, a[i].w); //长一定长于宽
sort (a + 1, a + 1 + t, cmp);
for (int i = 1; i <= t; i++)
{
f[i] = a[i].h;
for (int j = 1; j < i; j++)
if (a[j].l > a[i].l && a[j].w > a[i].w) //判断是否可以放上去
f[i] = max (f[i], f[j] + a[i].h);
ans = max (ans, f[i]);
}
printf ("%d", ans);
return 0;
}
来源:https://blog.csdn.net/qq_43010386/article/details/100042612