搜索
您的当前位置:首页正文

Leo搭积木【DP】

来源:易榕旅网

>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我竟然比赛时没做出来

因为长方体可以旋转,所以一个长方体有三种方式摆放(要维护 长 > > >宽)
求最长不下降序列的模板,首先得根据长从大到小排列所有的长方体,所有的 f [ i ] f[i] f[i]表示选第 i i i个长方体的最高高度,每次计算时直接枚举 1 1 1 ~ i − 1 i-1 i1之间的长方体,如果可以放上去的话就计算

状态转移方程: f [ i ] = m a x ( f [ i ] , f [ j ] + h [ i ] ) f[i]=max(f[i],f[j]+h[i]) f[i]=max(f[i],f[j]+h[i])


>代码

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

因篇幅问题不能全部显示,请点此查看更多更全内容

Top