hdu4939 Stupid Tower Defense dp好题

http://acm.hdu.edu.cn/showproblem.php?pid=4939

题意:塔防游戏:在长度为n的路上放置n座炮塔。有一只怪兽,经过单位长度需要时间t。现在有三种炮塔,

红塔:只对经过该点的怪兽造成每秒x点的伤害,

绿塔:怪兽经过这座塔之后的每一秒,每秒造成y点伤害(伤害是累加的,比如怪兽已经经过两座绿塔,那么伤害就是每秒2*y点),

蓝塔:使怪兽经过单位长度的时间增加z秒(时间也是累加的)。

现在要求你来建塔,使怪兽受到的伤害最大,求这个最大伤害。

题解:可以发现,红塔一定是建造在所有塔之后的,即最后面。因为红塔是及时伤害,会受蓝塔的效果影响,而且会减少绿塔的伤害。

那么可以想先是全部建造红塔。然后从第一个开始,每个换成蓝塔或者绿塔,每次更新答案。

dp[i][j]:前i座塔建造j座蓝塔的最大伤害。

转移方程:

a=dp[i-1][j]+(i-j-1)*y*(t+j*z),第i座不建蓝塔,建绿塔。

b=dp[i-1][j-1]+(i-j)*y*(t+(j-1)*z),第i座建蓝塔,不建绿塔。

dp[i][j]=max(a,b)

最后更新答案时,加上n-i段的红塔的伤害即可。

代码:

#include<bits/stdc++.h>
#define debug cout<<"aaa"<<endl
#define d(a) cout<<a<<endl
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;

const int N = 1500 + 5;
const int mod = 1000000000 + 7;
const double eps = 1e-8;
LL dp[N][N];//dp[i][j]:前i个有j个蓝塔的最大伤害 

int main(){
	int tt,cas=0,n;
	LL x,y,z,t,ans,a,b;
	scanf("%d",&tt);
	while(tt--){
		scanf("%d%lld%lld%lld%lld",&n,&x,&y,&z,&t);
		ans=n*x*t,mem(dp,0);
		for(int i=1;i<=n;i++){
			for(int j=0;j<=i;j++){//前i个中有j座蓝塔 
				if(j==0){
					dp[i][j]=dp[i-1][j]+(i-j-1)*y*t;//不放蓝塔
				}
				else{
					a=dp[i-1][j-1]+(i-j)*y*(t+(j-1)*z);//放蓝塔 
					b=dp[i-1][j]+(i-j-1)*y*(t+j*z);//不放蓝塔 
					dp[i][j]=max(a,b); 
				}
				//n-i段的伤害 
				a=dp[i][j]+(n-i)*x*(t+j*z)+(n-i)*(i-j)*y*(t+j*z);
				ans=max(a,ans);
			} 
		}
		printf("Case #%d: %lld\n",++cas,ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值