hdoj 4939 Stupid Tower Defense 【DP】



Stupid Tower Defense

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1908    Accepted Submission(s): 531


Problem Description
FSF is addicted to a stupid tower defense game. The goal of tower defense games is to try to stop enemies from crossing a map by building traps to slow them down and towers which shoot at them as they pass.

The map is a line, which has n unit length. We can build only one tower on each unit length. The enemy takes t seconds on each unit length. And there are 3 kinds of tower in this game: The red tower, the green tower and the blue tower. 

The red tower damage on the enemy x points per second when he passes through the tower.

The green tower damage on the enemy y points per second after he passes through the tower.

The blue tower let the enemy go slower than before (that is, the enemy takes more z second to pass an unit length, also, after he passes through the tower.)

Of course, if you are already pass through m green towers, you should have got m*y damage per second. The same, if you are already pass through k blue towers, the enemy should have took t + k*z seconds every unit length.

FSF now wants to know the maximum damage the enemy can get.
 

Input
There are multiply test cases.

The first line contains an integer T (T<=100), indicates the number of cases. 

Each test only contain 5 integers n, x, y, z, t (2<=n<=1500,0<=x, y, z<=60000,1<=t<=3)
 

Output
For each case, you should output "Case #C: " first, where C indicates the case number and counts from 1. Then output the answer. For each test only one line which have one integer, the answer to this question.
 

Sample Input
       
       
       
       
1 2 4 3 2 1
 

Sample Output
       
       
       
       
Case #1: 12
Hint
For the first sample, the first tower is blue tower, and the second is red tower. So, the total damage is 4*(1+2)=12 damage points.
 



题意:敌军要经过一段n单元的路径。敌军每经过一个单元耗时t s,且我们可以在n单元路径上每单元设置一个塔。

红塔——敌军通过时,会对他们造成每秒x点伤害

绿塔——敌军通过后,会对他们造成每秒y点的持续伤害(直到走完长度为n的路径)

蓝塔——敌军通过后,会对他们减速,使得他们通过每单位长度的时间延长z s

问你对敌军造成的最大伤害。


思路:考虑把红塔放在最后面的情况,可能在后面放 0-n 个,在这个假设下求出最优解。

用dp[i][j]表示 在我们用过j个蓝塔的前提下 敌军到达第i个单元时 所付出的最大代价,显然0 <= j <= i。

则对dp[i][j],每秒伤害加成cost = (i-j) * y,通过每单元时间加成time = t + j * z。

那么最优解 = max(所有合法的dp[i][j] + (n - i) * (cost + x), dp[n][k]其中0 <= k <= n).

我们只需每次由dp[i][j]推出dp[i+1][j+1] 和 dp[i+1][j],然后对dp[i][j]的状态维护最大值。最后求出状态

dp[n][n] 和 dp[n][n-1],在(0 <= k <= n)上维护dp[n][k]最大值。



AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 1500+1
#define LL long long
using namespace std;
LL dp[MAXN][MAXN];
int k = 1;
void solve()
{
    int n;
    LL x, y, z, t;
    scanf("%d%lld%lld%lld%lld", &n, &x, &y, &z, &t);
    memset(dp, 0, sizeof(dp));
    LL ans = 0;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j <= i; j++)
        {
            LL time = j * z + t, cost = (i - j) * y;
            dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j] + time * cost);
            dp[i+1][j] = max(dp[i+1][j], dp[i][j] + time * cost);
            ans = max(ans, dp[i][j] + (n-i) * (x + cost) * time);
        }
        if(i == n-1)
            for(int j = 0; j <= n; j++)
                ans = max(ans, dp[n][j]);
    }
    printf("Case #%d: %lld\n", k++, ans);
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--){
        solve();
    }
    return 0;
}




你可能感兴趣的:(hdoj 4939 Stupid Tower Defense 【DP】)