[BZOJ2964]Boss单挑战

本文介绍了一种复杂的RPG游戏战斗策略模拟算法,通过动态规划(DP)分解问题,分别处理魔法攻击、特技攻击和血量变化,最终确定主角能否在限定回合内击败Boss。

题目描述

\(RPG\)游戏中,最后一战是主角单挑\(Boss\),将其简化后如下:

主角的气血值上限为\(HP\),魔法值上限为\(MP\),愤怒值上限为\(SP\)\(Boss\)仅有气血值,其上限为\(M\)

现在共有\(N\)回合,每回合都是主角先行动,主角可做如下选择之一:

  1. 普通攻击:减少对方\(X\)的气血值,并增加自身\(DSP\)的愤怒值。(不超过上限)

  2. 法术攻击:共有\(N1\)种法术,第\(i\)种消耗\(B_i\)的魔法值,减少对方\(Y_i\)的气血值。(使用时要保证\(MP\)不小于\(B_i\)

  3. 特技攻击:共有\(N2\)种特技,第\(i\)种消耗\(C_i\)的愤怒值,减少对方\(Z_i\)的气血值。(使用时要保证\(SP\)不小于\(C_i\)

  4. 使用\(HP\)药水:增加自身\(DHP\)的气血值。(不超过上限)

  5. 使用\(MP\)药水:增加自身\(DMP\)的魔法值。(不超过上限)

之后\(Boss\)会攻击主角,在第\(i\)回合减少主角\(A_i\)的气血值。

刚开始时气血值,魔法值,愤怒值都是满的。当气血值小于等于\({0}\)时死亡。

如果主角能在这\(N\)个回合内杀死\(Boss\),那么先输出“\(Yes\)”,之后在同一行输出最早能在第几回合杀死\(Boss\)。(用一个空格隔开)

如果主角一定会被\(Boss\)杀死,那么输出“\(No\)”。

其它情况,输出“\(Tie\)”。

Input

输入的第一行包含一个整数\(T\),为测试数据组数。

接下来\(T\)部分,每部分按如下规则输入:

第一行九个整数\(N,M,HP,MP,SP,DHP,DMP,DSP,X\)

第二行\(N\)个整数\(A_i\)

第三行第一个整数\(N_1\),接下来包含\(N_1\)对整数\(B_i,Y_i\)

第四行第一个整数\(N_2\),接下来包含\(N_2\)对整数\(C_i,Z_i\)

对于第一个样例,主角的策略是:第一回合法术攻击,第二回合使用\(HP\)药水,第三回合特技攻击,第四回合普通攻击。
对于\(10\%\)的数据:\(N≤10,N1=N2=0\)
对于\(30\%\)的数据:\(N≤10,N1=N2=1\)
对于\(60\%\)的数据:\(N≤100,M≤10000,HP,MP,SP≤70\)
对于\(100\%\)的数据:\(1≤N≤1000,1≤M≤1000000,1≤HP,MP,SP≤1000,N1,N2≤10,DHP,A_i≤HP,DMP,B_i≤MP\)\(DSP,C_i≤SP,X,Y_i,Z_i≤10000,1≤T≤10\)

Output

输出共包含\(T\)行,每行依次对应输出一个答案。

Sample Input

2
5 100 100 100 100 50 50 50 20
50 50 30 30 30
1 100 40
1 100 40
5 100 100 100 100 50 50 50 10
50 50 30 30 30
1 100 40
1 100 40

Sample Output

Yes 4
Tie

很显然是一道\(DP\)题,但由于状态数以及转移方式太多了,导致我们无法直接\(DP\)

那就要考虑是否能将这些分开来考虑,它们之间是否有严格的约束关系

我们可以发现,在对战中,魔法攻击和特效攻击只与总回合数有关。

那我们就把这两个变量分开来进行类似于背包的\(DP\),最后在把血量放到背包里进行\(DP\)即可。

\(dp[i][j]\)表示前\(i\)个回合,血量为\(j\)能攻击的回合数。

若某一时刻的回合数达到了击杀最小回合数就可以击杀了。

\(dpm[i][j]\)表示\(i\)个回合,魔法值剩余\(j\)造成的最大伤害。

\(dps[i][j]\)表示\(i\)个回合,愤怒值剩余\(j\)造成的最大伤害,注意,愤怒值补充时会造成伤害。

\(Fmp[i]\)表示\(i\)个回合造成的最大魔法伤害。

\(Fsp[i]\)表示\(i\)个回合造成的最大特殊伤害。

代码如下

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <algorithm>
 
using namespace std;
 
#define LL long long
#define u64 unsigned long long
#define reg register
#define Raed Read
#define debug(x) cerr<<#x<<" = "<<x<<endl;
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,G,x) for(reg int i=(G).Head[x]; i; i=(G).Nxt[i])
 
inline int Read() {
    int res = 0, f = 1;
    char c;
    while (c = getchar(), c < 48 || c > 57)if (c == '-')f = 0;
    do res = (res << 3) + (res << 1) + (c ^ 48);
    while (c = getchar(), c >= 48 && c <= 57);
    return f ? res : -res;
}
 
template<class T>inline bool Min(T &a, T const&b) {
    return a > b ? a = b, 1 : 0;
}
template<class T>inline bool Max(T &a, T const&b) {
    return a < b ? a = b, 1 : 0;
}
 
const int N = 1e3+5, M = 1e3+5, mod = 1e9 + 9;
 
bool MOP1;
 
int n,m,hp,mp,sp,dhp,dmp,dsp,x,n1,n2,A[N],b[N],c[N],bb[N],cc[N];
 
struct T3100 {
    int dp[N][M],Fmp[M],Fsp[M],dpm[N][M],dps[N][M];
    inline void solve(void) {
        rep(i,1,n)rep(j,0,mp)dpm[i][j]=0;
        rep(i,1,n)rep(j,0,sp)dps[i][j]=0;
        rep(i,0,n)Fsp[i]=Fmp[i]=0;
        rep(i,0,n) {
            rep(j,0,mp)Max(Fmp[i],dpm[i][j]);
            rep(j,0,mp) {
                Max(dpm[i+1][min(j+dmp,mp)],dpm[i][j]);
                rep(k,1,n1)if(b[k]<=j)Max(dpm[i+1][j-b[k]],dpm[i][j]+bb[k]);
            }
        }
        rep(i,0,n) {
            rep(j,0,sp)Max(Fsp[i],dps[i][j]);
            rep(j,0,sp) {
                Max(dps[i+1][min(j+dsp,sp)],dps[i][j]+x);
                rep(k,1,n2) if(c[k]<=j)Max(dps[i+1][j-c[k]],dps[i][j]+cc[k]);
            }
        }
        int Ans=n+n;
        rep(i,0,n)rep(j,0,n)if(Fsp[i]+Fmp[j]>=m)Min(Ans,i+j);
        memset(dp,-63,sizeof dp);
        dp[1][hp]=1;
        rep(i,1,n) {
            rep(j,1,hp) {
                if(dp[i][j]>=Ans) {
                    printf("Yes %d\n",(int)i);
                    return;
                }
                if(A[i]<min(j+dhp,hp))Max(dp[i+1][min(j+dhp,hp)-A[i]],dp[i][j]);
                if(A[i]<j)Max(dp[i+1][j-A[i]],dp[i][j]+1);
            }
        }
        rep(i,1,hp)if(dp[n+1][i]>=0) {
            puts("Tie");
            return;
        }
        puts("No");
    }
} P100;
 
bool MOP2;
 
inline void _main(void) {
    int T=Read();
    while(T--) {
        n=Read(),m=Read(),hp=Read(),mp=Read(),sp=Read(),dhp=Raed(),dmp=Read(),dsp=Raed(),x=Read();
        rep(i,1,n)A[i]=Read();
        n1=Read();
        rep(i,1,n1)b[i]=Read(),bb[i]=Read();
        n2=Read();
        rep(i,1,n2)c[i]=Raed(),cc[i]=Read();
        P100.solve();
    }
}
 
signed main() {
#define offline1
#ifdef offline
    freopen("boss.in", "r", stdin);
    freopen("boss.out", "w", stdout);
    _main();
    fclose(stdin);
    fclose(stdout);
#else
    _main();
#endif
    return 0;
}

转载于:https://www.cnblogs.com/dsjkafdsaf/p/11276871.html

源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值