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