【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\n", 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\n");
69     printf("No\n");
70 }
71  
72 int main()
73 {
74     int t;
75     scanf("%d", &t);
76     while (t--) solve();
77 }

 

posted @ 2015-09-12 08:27  Lightning34  阅读(290)  评论(0编辑  收藏  举报