hdoj 4939 Stupid Tower Defense【dp】

题目:hdoj 4939 Stupid Tower Defense点击打开链接


来源:2014 Multi-University Training Contest 7


题意:塔防游戏,让你在一条直线上规划塔的放法,对经过的怪伤害最大,有三种类型的塔,第一种红塔,对经过的怪每一秒伤害x,第二种绿塔,对经过它之后的怪每秒伤害y,但是每增加一个绿塔伤害加 y,即第k个伤害 k* y ,然后第三种蓝塔,对经过的怪延时 z ,初始时经过一个单位的塔时间是t分钟,第 k 个延时 (t+k*z),求最大伤害。


分析:分析发现蓝塔和绿塔是随着放的数量的增多呈线性增长的,而红塔伤害不便,那么我把红塔放在最后段是最优,如果红塔的伤害足够高,也有可能全部放红塔,那么我们可以先 规划 出绿塔和蓝塔的放法,最后再枚举最后放几个红塔最好。


定义dp【i】【j】:在前 i 个位置放 j 个延时塔的最大伤害,那么对于当前塔,只有两种放法,要么绿塔,要么蓝塔。

则定义转移方程:dp【i】【j】= max(dp【i-1】【j】+( i - j - 1 )* y *(t +(z * j))(放绿塔),dp【i-1】【j-1】+ (i - j )* y *(t+(j-1)*z))(放蓝塔);


而对于红塔的数量,只用维护一个ans = max(ans,dp【i】【j】+(n-i)* x * (t + z * j)(后 n-i 个放红塔)+ (n-i)*(i - j) y *(t+j * z))(前面绿塔对后面的伤害)

注意考虑全部红塔的情况


代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
#include <utility>
#define Del(a,b) memset(a,b,sizeof(a))
const long long N = 1600;
using namespace std;

long long dp[N][N];

int main()
{
    long long T;
    scanf("%I64d",&T);
    for(long long cas=1;cas<=T;cas++)
    {
        long long n,x,y,z,t;
        scanf("%I64d%I64d%I64d%I64d%I64d",&n,&x,&y,&z,&t);
        memset(dp,0,sizeof(dp));
        long long ans = n * x * t;
        for(long long i=1;i<=n;i++)
        {
            for(long long j=0;j<=i;j++)
            {
                dp[i][j]=max(dp[i][j],dp[i-1][j]+(i-j-1)*y*(t+j*z));
                if(j!=0)
                    dp[i][j]=max(dp[i][j],dp[i-1][j-1]+(i-j)*y*(t+(j-1)*z));
                ans=max(ans,dp[i][j]+(n-i)*(x+(i-j)*y)*(t+j*z));
            }
        }
        printf("Case #%I64d: %I64d\n",cas,ans);
    }
    return 0;
}


你可能感兴趣的:(Algorithm,游戏,动态规划,iostream,CString)