Yet Another Monster Killing Problem

题意:
有n个怪兽,每个怪兽的战斗力为a[i]。

有m个英雄,每个英雄都有两个属性pi(战斗力)和si(耐力值),每杀死一个怪兽耐力值-1。

每天都需要派一个英雄去杀怪兽,如果该英雄的战斗力低于怪兽或者耐力值没了,则这一天结束。
问你最少多少天能杀完怪兽?

思路:

用k[i]数组记录每个耐力值的最大攻击力值

再按攻击力值填充耐力值为0的地方,比如k[2]=8说明耐力值为2的攻击力为8 没有耐力值为1的所以k[1]=0

这时 令k[1]=8,说明耐力值为1的攻击力为8,表明当攻击力为8时,我可以攻打一个,也可以攻打两个

反向填充,耐力值逐渐减少而攻击力取最大值,意在原攻击力匹配k个耐力值,可以都用,或者用一个,或者用两个。。等等

也会取代耐力值小并且攻击力也小的英雄

                                          for (int i = n; i >= 0; i--) k[i] = max(k[i], k[i + 1]);

对于每个a[i]与k[1]比较,此时k[1]为英雄攻击力最大值,若是任一a[i]大于k[1]说明无法成功,输出-1。

之后遍历怪兽的攻击力,取a[i+j]和a[i+j+1]的最大值与英雄耐力值为j+1时的攻击力比较,

一旦英雄攻击失败,天数++,并且记录此时的i(i为第几只怪兽),再接着遍历

                                          for (; j <= n; j++) {
                                                  maxn = max(maxn, a[j + i]);
                                                  if (k[j + 1] < maxn) break; //因为每个英雄可以无限次使用
                                          }
                                         day++;
                                         i += j;

按顺序攻击,所以k数组的目的就是在攻击力可以的情况下使耐力尽可能大。

注意:英雄是按顺序攻击怪兽,若是这个英雄没有攻击成功,下一个英雄第二天继续攻击

          每天都会生成新的耐力值

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<stack>
 7 #include <bitset>
 8 #include<set>
 9 #include<map>
10 #include<unordered_map>
11 #include<vector>
12 #include<cmath>
13 #include<string>
14 using namespace std;
15 typedef long long ll;
16 #define inf 99999999
17 const int maxn = 2e5;
18 int t, n, m;
19 int a[maxn], k[maxn];
20 struct node {
21     int p;
22     int s;
23 }her[maxn];
24 int main() {
25     cin >> t;
26     while(t--){
27         cin >> n;
28         for (int i = 1; i <= n; i++) {
29             cin >> a[i];
30         }
31         cin >> m;
32         for (int i = 1; i <= m; i++) {
33             cin >> her[i].p >> her[i].s;
34             //记录每个耐力值的最大攻击力值
35             k[her[i].s] = max(k[her[i].s], her[i].p);
36         }
37         for (int i = n; i >= 0; i--) k[i] = max(k[i], k[i + 1]);
38         int day = 0;
39         int f = 0;
40         for (int i = 1; i <= n;) {
41             if (a[i] > k[1]) {
42                 f = 1;
43                 cout << "-1" << endl;
44                 break;
45             }
46             int j = 0;
47             int maxn = 0;
48             for (; j <= n; j++) {
49                 maxn = max(maxn, a[j + i]);
50                 if (k[j + 1] < maxn) break; //因为每个英雄可以无限次使用
51             }
52             day++;
53             i += j;
54         }
55         if (f == 0) {
56             cout << day << endl;
57         }
58         for (int i = 0; i <= n; i++) k[i] = 0;
59     }
60     return 0;
61 }

 

posted @ 2020-07-28 11:15  吉吉的奥利奥  阅读(26)  评论(0编辑  收藏