题目: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;
}