hdu 4939 Stupid Tower Defense(DP)2014多校训练第7场

Stupid Tower Defense

                                                                        Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

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秒。
有3种塔,红塔可以在当前格子每秒造成x点伤害,绿塔可以在之后的格子每秒造成y点伤害,蓝塔可以使通过单位长度的时间增加z秒。问如何安排3种塔的顺序使得造成的伤害最大,输出最大伤害值。

分析:如果要安排红塔,则红塔在前面没有在后面造成的伤害大。所以可以枚举红塔的数量i,对前n-i座塔进行dp。
设dp[i][j]表示前i个单位长度中有j个蓝塔造成的最大伤害,则
dp[i][j] = max(dp[i-1][j-1] + (i - j) * y * (t + (j - 1) * z),  dp[i-1][j] + (i - j - 1) * y * (t + j * z))
其中,(i - j) * y * (t + (j - 1) * z)表示i-j个绿塔在第i 个格子造成的伤害,(i - j - 1) * y * (t + j * z)表示i-j-1个绿塔在第i个格子造成的伤害。
求出dp[i][j]以后,则红塔数量为n-i时的总伤害为damage=dp[i][j] + (n - i) * x * (t + j * z) + (n - i) * (t + j * z) * (i - j) * y(后n-i个红塔造成的伤害加上前i-j个绿塔在后n-i个格子造成的伤害),所以最终的ans=max(ans, damage).

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1505;
typedef __int64 LL;
LL dp[N][N];
int main()
{
    LL x, y, z, t, n, i, j;
    int T, cas = 0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d%I64d%I64d%I64d%I64d",&n,&x,&y,&z,&t);
        memset(dp, 0, sizeof(dp));
        LL ans = n * t * x; //全部放红塔
        for(i = 1; i <= n; i++)  //前i个单位长度
        {
            for(j = 0; j <= i; j++) // 蓝塔数量
            {
                if(j == 0)
                    dp[i][j] = dp[i-1][j] + (i - j - 1) * y * t;
                else
                {
                    LL tmp1 = dp[i-1][j-1] + (i - j) * y * (t + (j - 1) * z); //第j个单位长度放蓝塔
                    LL tmp2 = dp[i-1][j] + (i - j - 1) * y * (t + j * z); //第j个单位长度不放蓝塔
                    dp[i][j] = max(tmp1, tmp2);
                }
                ans = max(ans, dp[i][j] + (n - i) * x * (t + j * z) + (n - i) * (t + j * z) * (i - j) * y);
            }
        }
        printf("Case #%d: %I64d\n", ++cas, ans);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值