zoukankan      html  css  js  c++  java
  • 【BZOJ 2964】Boss单挑战

    Description

      某RPG游戏中,最后一战是主角单挑Boss,将其简化后如下:
      主角的气血值上限为HP,魔法值上限为MP,愤怒值上限为SP;Boss仅有气血值,其上限为M。
      现在共有N回合,每回合都是主角先行动,主角可做如下选择之一:
      1. 普通攻击:减少对方X的气血值,并增加自身DSP的愤怒值。(不超过上限)
      2. 法术攻击:共有N1种法术,第i种消耗Bi的魔法值,减少对方Yi的气血值。(使用时要保证MP不小于Bi)
      3. 特技攻击:共有N2种特技,第i种消耗Ci的愤怒值,减少对方Zi的气血值。(使用时要保证SP不小于Ci)
      4. 使用HP药水:增加自身DHP的气血值。(不超过上限)
      5. 使用MP药水:增加自身DMP的魔法值。(不超过上限)
      之后Boss会攻击主角,在第i回合减少主角Ai的气血值。
      刚开始时气血值,魔法值,愤怒值都是满的。当气血值小于等于0时死亡。
      如果主角能在这N个回合内杀死Boss,那么先输出“Yes”,之后在同一行输出最早能在第几回合杀死Boss。(用一个空格隔开)
      如果主角一定会被Boss杀死,那么输出“No”。
      其它情况,输出“Tie”。

    Input

      输入的第一行包含一个整数T,为测试数据组数。
      接下来T部分,每部分按如下规则输入:
      第一行九个整数N, M, HP, MP, SP, DHP, DMP, DSP, X。
      第二行N个整数Ai。
      第三行第一个整数N1,接下来包含N1对整数Bi, Yi。
      第四行第一个整数N2,接下来包含N2对整数Ci, Zi。

    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
    样例说明
      对于第一个样例,主角的策略是:第一回合法术攻击,第二回合使用HP药水,第三回合特技攻击,第四回合普通攻击。

    HINT

      对于100%的数据:1 ≤ N ≤ 1000,1 ≤ M ≤ 1000000,1 ≤ HP,MP,SP ≤ 1000,N1,N2 ≤ 10,DHP,Ai ≤ HP,DMP,Bi ≤ MP,DSP,Ci ≤ SP,X,Yi,Zi ≤ 10000,1 ≤ T ≤ 10。

    分析:

      考虑到HP、MP、SP之间是相互独立的,且MP、SP是回合无关的(只与回合总数有关,与在哪一回合攻击无关),所以可以先分别对MP和SP进行DP,F[i][j]表示进行i次MP/SP的操作后,剩下MP/SP为j,对Boss造成的最大伤害,再记录G1[i]和G2[i]分别表示进行i次MP/SP的操作,对Boss造成的最大伤害。

      枚举i、j,统计当G1[i]+G2[j]>=M时,i+j的最小值mincost,这就是打倒Boss的最少操作次数(与HP无关)。

      最后再考虑HP,HP是和回合有关的,所以DP的时候要考虑回合。用F[i][j]表示在第i回合之前,还剩下的HP为j,最多有多少次MP/SP的操作次数,包括当前第i回合。

      若存在F[i][j]>=mincost(i<=n、j>0),那么输出Yes,最小的i即为答案。

      否则,判断No或Tie,在DP之前将F[i][j]初始化为极小的负数,若存在F[N + 1][j]>=0(j>0),则表示N回合之内主角可以不死,却也打不死Boss,即输出Tie,否则输出No。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3  
     4 int n, m, hp, mp, sp, dhp, dmp, dsp, x;
     5 int a[1010], kmp[1010][2], ksp[1010][2], km, ks;
     6 int dp_mp[1010][1010], dp_sp[1010][1010], fm[1010], fs[1010];
     7 int f[1010][1010];
     8  
     9 int min(int A, int B) { return A < B ? A : B;}
    10 void checkmin(int &A, int B) { A > B ? A = B : 0;}
    11 void checkmax(int &A, int B) { A < B ? A = B : 0;}
    12  
    13 int solve()
    14 {
    15     memset(dp_mp, 0, sizeof dp_mp);
    16     memset(dp_sp, 0, sizeof dp_sp);
    17     memset(fm, 0, sizeof fm);
    18     memset(fs, 0, sizeof fs);
    19     memset(f, 180, sizeof f);
    20     scanf("%d%d%d%d%d", &n, &m, &hp, &mp, &sp);
    21     scanf("%d%d%d%d", &dhp, &dmp, &dsp, &x);
    22     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    23     scanf("%d", &km);
    24     for (int i = 1; i <= km; i++)
    25         scanf("%d%d", &kmp[i][0], &kmp[i][1]);
    26     scanf("%d", &ks);
    27     for (int i = 1; i <= ks; i++)
    28         scanf("%d%d", &ksp[i][0], &ksp[i][1]);
    29     for (int i = 0; i <= n; i++)
    30     {
    31         for (int j = 0; j <= mp; j++)
    32         {
    33             checkmax(fm[i], dp_mp[i][j]);
    34             for (int k = 1; k <= km; k++) if (j >= kmp[k][0])
    35                 checkmax(dp_mp[i + 1][j - kmp[k][0]], dp_mp[i][j] + kmp[k][1]);
    36             checkmax(dp_mp[i + 1][min(j + dmp, mp)], dp_mp[i][j]);
    37         }
    38     }
    39     for (int i = 0; i <= n; i++)
    40     {
    41         for (int j = 0; j <= sp; j++)
    42         {
    43             checkmax(fs[i], dp_sp[i][j]);
    44             for (int k = 1; k <= ks; k++) if (j >= ksp[k][0])
    45                 checkmax(dp_sp[i + 1][j - ksp[k][0]], dp_sp[i][j] + ksp[k][1]);
    46             checkmax(dp_sp[i + 1][min(j + dsp, sp)], dp_sp[i][j] + x);
    47         }
    48     }
    49     int mincost = 99999999;
    50     for (int i = 0; i <= n; i++)
    51         for (int j = 0; j <= n; j++)
    52             if (fm[i] + fs[j] >= m)
    53                 checkmin(mincost, i + j);
    54     f[1][hp] = 1;
    55     for (int i = 1; i <= n; i++)
    56     {
    57         for (int j = 1; j <= hp; j++)
    58         {
    59             if (f[i][j] >= mincost)
    60                 return printf("Yes %d
    ", i);
    61             if (j > a[i]) checkmax(f[i + 1][j - a[i]], f[i][j] + 1);
    62             if (min(j + dhp, hp) > a[i])
    63                 checkmax(f[i + 1][min(j + dhp, hp) - a[i]], f[i][j]);
    64         }
    65     }
    66     for (int j = 1; j <= hp; j++)
    67         if (f[n + 1][j] >= 0)
    68             return printf("Tie
    ");
    69     printf("No
    ");
    70 }
    71  
    72 int main()
    73 {
    74     int t;
    75     scanf("%d", &t);
    76     while (t--) solve();
    77 }
  • 相关阅读:
    jquery 序列化form表单
    nginx for windows 安装
    nodejs idea 创建项目 (一)
    spring 配置 shiro rememberMe
    idea 2018 解决 双击shift 弹出 search everywhere 搜索框的方法
    redis 在windows 集群
    spring IOC控制反转和DI依赖注入
    redis 的安装
    shiro 通过jdbc连接数据库
    handlebars的用法
  • 原文地址:https://www.cnblogs.com/lightning34/p/4802526.html
Copyright © 2011-2022 走看看