Misunderstood-Missing-逆向DP

本文介绍了一种使用逆向动态规划(DP)解决游戏战斗策略问题的方法,旨在最大化玩家角色在n轮战斗中的总伤害输出。通过分析攻击力、成长值及不同选择对后续战斗的影响,设计了包含额外变量的DP算法,详细解析了代码实现。

Misunderstood … Missing

记忆深刻......打铁没做出来的题

题意 :

打怪,有 A 的攻击力,有 D 的成长,初始均为 0,有 n 轮。

同时有三个数组 a[1:n],b[1:n],c[1:n]

对于每一轮:

首先,攻击力永久性成长 A=A+D;然后,在下面三个选择中选择一种行为:

①、发起进攻,产生 A+ai的伤害。

②、增加成长 D=D+bi。

③、永久性增加攻击力 A=A+ci问产生最大总伤害为多少

思路:

逆向DP,DP [ i ]代表的是从第i天到第n天产生的最大伤害,转移方程分析一下:
如果 这一天选择 ① 那么 对后面的影响是伤害增加 ai,选择②对后面影响的是攻击的那些天数伤害都增加 ( bi * (j-i))

选择③对后面的影响是,增加伤害为攻击的天数 * c[ i ],那么dp 需要增加两个变量 ,一个是方便计算选择②的情况

增加一个攻击了的天数下标和,另一个是 当前攻击的天数数目和,初始值为 dp[ n ] [ 1 ] [ n ] =  a [ n ] 详见代码:

#include<bits/stdc++.h>
using namespace std;
#define maxn 111
#define ll long long
ll t,n,a[maxn],b[maxn],c[maxn];
ll dp[3][maxn][maxn*maxn/2],ans;
int main()
{
    scanf("%lld",&t);
    while(t--)
    {
        ans=0;
        memset(dp,0,sizeof(dp));
        scanf("%lld",&n);
        for(int i=1; i<=n; i++)
            scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
        dp[n&1][1][n]=a[n];
        for(int i=n-1; i>=1; i--)
        {
            for(int j=1; j+i<=n; j++)
            {
                int low = (i+i+j)*(j-1)/2+n;
                int up = (n+n-(j-1))*j/2;
                for(int k=low; k<=up; k++)
                {
                    dp[i&1][j+1][k+i]=max(dp[i&1][j+1][k+i],dp[(i+1)&1][j][k]+a[i]);
                    dp[i&1][j][k]=max(dp[i&1][j][k],dp[(i+1)&1][j][k]+(k-j*i)*b[i]);
                    dp[i&1][j][k]=max(dp[i&1][j][k],dp[(i+1)&1][j][k]+j*c[i]);
                }
            }
        }
        for(int j=1; j<=n; j++)
            for(int k=n; k<=5050; k++)
                ans=max(ans,dp[1][j][k]);
        printf("%lld\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值