度度熊与邪恶大魔王 DP | 完全背包

Problem Description

度度熊为了拯救可爱的公主,于是与邪恶大魔王战斗起来。

邪恶大魔王的麾下有n个怪兽,每个怪兽有a[i]的生命值,以及b[i]的防御力。

度度熊一共拥有m种攻击方式,第i种攻击方式,需要消耗k[i]的晶石,造成p[i]点伤害。

当然,如果度度熊使用第i个技能打在第j个怪兽上面的话,会使得第j个怪兽的生命值减少p[i]-b[j],当然如果伤害小于防御,那么攻击就不会奏效。

如果怪兽的生命值降为0或以下,那么怪兽就会被消灭。

当然每个技能都可以使用无限次。

请问度度熊最少携带多少晶石,就可以消灭所有的怪兽。

Input

本题包含若干组测试数据。

第一行两个整数n,m,表示有n个怪兽,m种技能。

接下来n行,每行两个整数,a[i],b[i],分别表示怪兽的生命值和防御力。

再接下来m行,每行两个整数k[i]和p[i],分别表示技能的消耗晶石数目和技能的伤害值。

数据范围:

1<=n<=100000

1<=m<=1000

1<=a[i]<=1000

0<=b[i]<=10

0<=k[i]<=100000

0<=p[i]<=1000

Output

对于每组测试数据,输出最小的晶石消耗数量,如果不能击败所有的怪兽,输出-1

Sample Input
1 2
3 5
7 10
6 8
1 2
3 5
10 7
8 6
Sample Output
6
18






DP
根据输入的攻击力及耗费的晶石把任意生命力和血量的怪兽处理出来,之后O(1)查找每个怪兽消耗的晶石。时间1000*10*1000(也就7个零)

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<math.h>
 4 #include<algorithm>
 5 #include<string.h>
 6 using namespace std;
 7 __int64 dp[1005][15];
 8 int p[1111], k[1111];
 9 int a[100000 + 5], b[100000 + 5];
10 int main()
11 {
12     int n, m;
13     while (~scanf("%d%d", &n, &m))
14     {
15         int i,j, u;
16         memset(dp, 111111, sizeof(dp));//初始化
17         dp[0][0] = 0;
18         int maxb = 0, maxp = 0;
19         for (i = 1; i <= n; i++)
20         {
21             scanf("%d%d", &a[i], &b[i]);
22             maxb = max(b[i], maxb);
23         }
24         for (i = 1; i <= m; i++)
25         {
26             scanf("%d%d", &k[i], &p[i]);
27             maxp = max(p[i], maxp);
28         }
29         //------------特判-----------
30         if (maxp <= maxb)//最大的攻击力小于等于最大的防御力即不能对此怪造成伤害。
31         {
32             printf("-1
");
33             continue;
34         }
35         //---------------------------
36         //-------------血为i 防御力为j------------------
37         __int64 t, x;
38         for (i = 1; i <= 1000; i++)
39         {
40             for (j = 0; j <= 10; j++)
41             {
42                 x = t = dp[i][j];
43                 for (u = 1; u <= m; u++)
44                 {
45                     if (p[u] <= j)
46                         continue;
47                     if (p[u] - j >= i)
48                         x = k[u];
49                     else
50                         x = dp[i - p[u] + j][j] + k[u];
51                     t = min(x, t);
52                 }
53                 dp[i][j] = t;
54             }
55         }
56         //-------------------------------------------------
57         __int64 sum = 0;
58         for (i = 1; i <= n; i++)
59         {
60             sum += dp[a[i]][b[i]];
61         }
62         cout << sum << endl;
63     }
64 }