hdu1069(lis的长方体堆叠模型)

/*
translation:
	给出n中不同类型的石块,每种类型的石块长宽高都不一样。对于两块石块a,b。只有当a的底面的长宽严格小于b的长宽时,
	a才能摆放在b的上面。问最多能够将石块叠加到多高。
solution:
	lis的长方体堆叠模型,dp
	这道题很明显使用dp来做,(其实用搜索也可以吧,数据量不是很大)具体做法是先按照长宽或者宽长对各类的长方体进行排列。然后在直接套上lis的模型即可。
	注意每个长方体有6种不同的摆放状态。所以可以将其看成6个类型的长方体。这样就好处理了。还要注意的是一旦用上一类
	长方体,在接下来就不可能再次用到了。所以还可以将每个类型长方体看成只有一个。
note:
	# 原本想的是可能是背包模型,后来仔细观察发现堆叠的顺序是有讲究的,就想是否是lis。但是又被我否决了,因为lis的
	顺序是按照已经给出的顺序不变的。而此题明显取走两种石块时是可以不按照输入顺序的。总不能预先排序再dp吧?那是肯定不可能
	的!最后实在想不出来了,看了下题解,我草还真是预先排序......我这嘴TM开过光......
	* lis的长方体堆叠模型,仔细想了一下,这种模型还有可能被用来考察dilworth定理。先RT下。
date:
	2016.10.29
*/
#include 
#include 
#include 
#include 
#include 

using namespace std;
const int maxn = 35;
const int inf = 1e8;

struct Block{
	int x, y, z;
	Block(int x_=0, int y_=0, int z_=0):x(x_),y(y_),z(z_){}
};
vector b;
int n, dp[maxn*6];

bool cmp(const Block& lhs, const Block& rhs)
{
	if(lhs.x == rhs.x)	return lhs.y > rhs.y;
	else				return lhs.x > rhs.x;
}

bool inside(int i, int j)	//i可以嵌套在j上面
{
	return (b[i].x < b[j].x && b[i].y < b[j].y);
}

int main()
{
	//freopen("in.txt", "r", stdin);
	int T = 0;
    while(~scanf("%d", &n) && n){
		int x, y, z;	b.clear();
		for(int i = 0; i < n; i++){
			scanf("%d%d%d", &x, &y, &z);
			b.push_back(Block(x, y, z));	b.push_back(Block(y, x, z));
			b.push_back(Block(x, z, y));	b.push_back(Block(z, x, y));
			b.push_back(Block(y, z, x));	b.push_back(Block(z, y, x));
		}
		n = b.size();
		sort(b.begin(), b.end(), cmp);

		memset(dp, 0, sizeof(dp));
		int ans = -inf;
		for(int i = 0; i < n; i++){
			dp[i] = b[i].z;
			for(int j = 0; j < i; j++) if(inside(i, j)){
				dp[i] = max(dp[i], dp[j] + b[i].z);
			}
			ans = max(ans, dp[i]);
		}
		ans = max(0, ans);
		printf("Case %d: maximum height = %d\n", ++T, ans);
    }
    return 0;
}

你可能感兴趣的:(=====动态规划=====,基本dp)