HDU_4001_To miss our children time_动态规划

今天用师兄的机械键盘打比赛感觉爽爆了有木有!!!


题意:

在地上有n个block,每个block有四个属性:长、宽、厚度(三个属性中长宽可互换,厚度不可和长宽换)、种类,要一个叠一个地使叠成的塔最高。种类有三种:0:下面的块的长宽必须小于等于该块;1:下面的块的长宽必须小于等于该块,并且长宽中有一个不等于该块;2:下面的块的长宽必须小于该块。问塔最高多高。



Input

The input has many test cases.
For each test case the first line is a integer n ( 0< n <= 1000) , the number of blocks.
From the second to the n+1'th lines , each line describing the i�1'th block's a,b,c,d (1 =< ai,bi,ci <= 10^8 , d = 0 or 1 or 2).
The input end with n = 0.
 

Output

Output a line contains a integer describing the highest "Skyscraper"'s height using the n blocks.


从一个块转移到另一个块,这里有一个性质保证单向遍历:按照长宽排序,后面的块不可能排在前面的块下面,要求苛刻的块没必要排在要求宽松的块后面,状态转移就是dp[i]=max(dp[i],dp[j]+p[i].h)

一开始队友用了swap结果WA,后来才知道是因为g++不认swap函数。


代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define LL long long
#define mxn 9099 
struct fuck
{
	LL a, b, d;
	LL c;
	bool operator < (const fuck& in)const{
		if(a!=in.a)	return a<in.a;
		if(b!=in.b)	return b<in.b;
		if(d!=in.d)	return d>in.d;
	}
}p[mxn];
LL maxx( LL u, LL v ){
	if( u >= v )
		return u;
	else return v;
}
LL dp[mxn];
int main(){
	LL  n;
	while( scanf("%I64d",&n) ){
		if( n == 0 )
			break;
		memset( dp, 0, sizeof( dp ) );
		for( LL i = 1; i <= n; ++i ){
			scanf("%I64d%I64d%I64d%I64d",&p[i].a,&p[i].b,&p[i].c,&p[i].d);
			if( p[i].a > p[i].b )
				swap( p[i].a, p[i].b );
     		}
		p[0].a = p[0].b = p[0].c = p[0].d = 0;
		sort( p + 1, p + n + 1 );
		for( LL i = 1; i <= n; ++i )
			for( LL j = i - 1; j >= 0; --j ){
				if( p[i].d == 0 && p[i].a >= p[j].a && p[i].b >= p[j].b )
					dp[i] = max( dp[i], dp[j] + p[i].c );
				if( p[i].d == 1 && p[i].a >= p[j].a && p[i].b >= p[j].b && p[i].a * p[i].b > p[j].a * p[j].b )
					dp[i] = max( dp[i], dp[j] + p[i].c );
				if( p[i].d == 2 && p[i].a > p[j].a && p[i].b > p[j].b )
					dp[i] = max( dp[i], dp[j] + p[i].c );
			}
		LL ans = -1;
		for( LL i = 1; i <= n; ++i )
			ans = maxx( ans, dp[i] );
		printf("%I64d\n",ans);
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值