对于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造成的最大伤害。
最后再考虑HP,HP是和回合有关的,所以DP的时候要考虑回合。用F[i][j]表示在第i回合之前,还剩下的HP为j,最多有多少次MP/SP的操作次数,包括当前第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 }