[noip模拟题]LGTB 玩THD

  LGTB 最近在玩一个类似DOTA 的游戏名叫THD
  有一天他在守一座塔,对面的N 个小兵排成一列从近到远站在塔前面
每个小兵有一定的血量hi,杀死后有一定的金钱gi
  每一秒,他都可以攻击任意一个活着的小兵,对其造成P 点伤害,如果小兵的血量低于1 点,小兵死亡,他
得到金钱。他也可以不攻击任何小兵。
  每一秒LGTB 攻击完毕之后,塔会攻击距离塔最近的一个活着的小兵,对其造成Q 点伤害,如果小兵的血
量低于1 点,小兵死亡,LGTB 不会得到金钱
  现在LGTB 想知道,在他选择最优策略时,他能得到多少钱。
输入
输入第一行包含3 个整数P, Q, N
接下来N 行,每行包含2 个整数hi, gi
第i 个小兵和塔之间的距离为i
输入的意义如题面所示
对于20% 的数据,$1 leqslant N leqslant 4$
对于50% 的数据,$1 leqslant N leqslant 20$
对于100% 的数据,$20 leqslant P, Q leqslant 200$, $1 leqslant N leqslant 100$, $1 leqslant h_{i} leqslant 200$, $1 leqslant g_{i} leqslant 10^{6}$
输出
输出包含一个整数W,代表LGTB 最多能获得的金钱
样例
样例输入样例输出
20 60 3
80 100
80 200
120 300
500
4


  假如我们要得到第$i$个士兵的收益,我们可以贪心地让塔打小兵尽量多的次数,然后让LGTB去补刀。当然这样不一定一次能打死,所以需要在补刀之前还需打上几次。

  所以用$f[i][j]$表示当前考虑到第$i$个士兵时(前面的士兵已经被消灭了),当前积攒了$j$次攻击机会时的最大收益,

  第一种操作是不管这个小兵,那么直接让塔把它打死,那么就可以得到一些攻击机会。

  第二种操作是在塔把它打残后补刀,这样会消耗一些攻击机会,同时会得到一些收益。

Code

 1 #include<iostream>
 2 #include<fstream>
 3 #include<cstring>
 4 using namespace std;
 5 ifstream fin("thd.in");
 6 ofstream fout("thd.out");
 7 typedef class xb{
 8     public:
 9         int money;                                        //钱数 
10         int health;                                        //生命值 
11         int kill;
12         int pkill;
13 }xb;
14 int p,q,n;
15 xb *xbs;
16 int f[101][1001];
17 istream& operator >>(istream& in, xb& x){
18     in>>x.health>>x.money;
19 }
20 int main(){
21     fin>>p>>q>>n;
22     xbs = new xb[(const int)(n + 1)];
23     for(int i = 1; i <= n; i++){
24         fin>>xbs[i];
25         xbs[i].kill = ( xbs[i].health - 1 )/q;                    //塔把士兵i打成残血的次数 
26         xbs[i].pkill = ( xbs[i].health - xbs[i].kill * q - 1)/p + 1;    //塔把士兵打成残血后,玩家打死士兵的次数 
27     }
28     for(int i = 0;i <= n;i++){                    //f数组初始化 
29         for(int j =0; j <= 1000;j++){
30             f[i][j] = -1000000;
31         }
32     }
33     f[0][1] = 0;                           34                                          
35     for(int i = 1; i <= n;i++){
36         for(int j = 0;j <= 1000;j++){
37             f[i][j + xbs[i].kill + 1] = max(f[i - 1][j], f[i][j + xbs[i].kill + 1]);
38             if(j >= xbs[i].pkill - xbs[i].kill){
39                 f[i][j - (xbs[i].pkill - xbs[i].kill)] = max(f[i - 1][j] + 
40                     xbs[i].money, f[i][j - (xbs[i].pkill - xbs[i].kill)]);
41             }
42         }
43     }
44     int maxv = f[n][0];
45     for(int i = 0;i <= 1000;i++)
46         maxv = max(f[n][i], maxv);
47     fout<<maxv;
48     return 0;
49 }


 

原文地址:https://www.cnblogs.com/yyf0309/p/5671918.html