首页 > 代码库 > hdu4939Stupid Tower Defense(DP)

hdu4939Stupid Tower Defense(DP)

题目:hdu4939Stupid Tower Defense(DP)


题目大意:保卫游戏。给出一条长度n的道路,这条道路上每个单元长度可以放一个塔。现在有三种塔:红塔:怪经过这个塔的时候受到X的伤害每秒。绿塔:怪经过这个塔之后,以后的每秒都受到Y的伤害。蓝塔:怪经过这个塔后,之后每经过单元长度的时间加长为t + Z;问怎样选择这三种塔能够使得伤害值最大。


解题思路:一开始没有想到这是DP, 看了题解才发现放塔的时候红塔应该放在最后面最优,那么就只要放蓝绿塔就行,而且前面哪个位置放了蓝绿塔对后面是没有影响,只有蓝绿塔的数目和后面的伤害值有关。这样的话,dp【i】【j】代表前面i个位置,放了j个绿塔,i - j个蓝塔的最大伤害值(后面的都是n - i都是红塔但是伤害值没有计算在内)。然后分别考虑i + 1个位置是放蓝塔还是放绿塔。最后就是维护最大值,这个过程中,任何的一种方法都可能造成最大伤害。然后要注意后面的n - i的红塔的伤害值最后要加上,并且后面的单元长度的蓝塔的伤害也不能漏掉。


代码:

#include <cstdio>
#include <cstring>

typedef __int64 ll;
//typedef long long ll;

const int N = 1505;
ll n, x, y, z, t;
ll dp[N][N];

ll Max (const ll a, const ll b ) { return a > b ? a: b; }

ll solve () {

	memset (dp, 0, sizeof (dp));
	ll ans = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= i; j++) {

			ll T = t + j * z;//经过一个单元的时间
			ll W = T * (i - j) * y;//一个单元长度(i - j)个绿塔的伤害
			dp[i + 1][j + 1] = Max (dp[i + 1][j + 1],dp[i][j] + W);//第i+1个单元放蓝塔
			dp[i + 1][j] = Max (dp[i + 1][j], dp[i][j] + W);       //第i+1个单元放绿塔
			ans = Max (ans, dp[i][j] + (n - i) * (x * T + W));     //i单元后面全部放红塔
		}
	}

	for (int i = 0; i <= n; i++)
		ans = Max (ans, dp[n][i]);
	return ans;
}

int main () {

	int cas;
	scanf ("%d", &cas);
	for (int i = 1; i <= cas; i++) {
	//	scanf ("%lld%lld%lld%lld%lld", &n, &x, &y, &z, &t);
		scanf ("%I64d%I64d%I64d%I64d%I64d", &n, &x, &y, &z, &t);
		printf ("Case #%d: %I64d\n", i, solve());
	//	printf ("Case #%d: %lld\n", i, solve());
	}
	return 0;
}