首页 > 代码库 > 2017百度之星资格赛1003 度度熊与邪恶大魔王

2017百度之星资格赛1003 度度熊与邪恶大魔王

度度熊与邪恶大魔王

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

邪恶大魔王的麾下有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 

18

题目大意:找出能否打败n个怪兽所消耗的最小晶石数。如果不能打败,就输出-1。

解题思路:完全背包问题。因为n的数据量较大,所以我们对每一种可能的怪兽血量和防御力枚举。枚举所有情况。对m个技能进行完全背包。

ps:注意一点就是时间上要优化一下,不然会TLE。

AC代码:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int INF=0x3f3f3f3f;
 6 struct Node{
 7     int a,b;
 8 }num[100050];
 9 struct Node2{
10     int p,k;
11 }ak[1005];
12 int dp[1005][15];    //用二维数组,之前用了三维内存爆了。
13 int main(){
14     int n,m;
15     while(~scanf("%d%d",&n,&m))
16     {
17         for(int i=1;i<=n;i++){
18             scanf("%d %d",&num[i].a,&num[i].b);
19         }
20         for(int i=1;i<=m;i++){
21             scanf("%d %d",&ak[i].k,&ak[i].p);
22         }
23         for(int i=0;i<1005;i++){
24             for(int j=0;j<10;j++){
25                 dp[i][j]=INF;
26             }
27         }
28         for(int i=0;i<15;i++){
29                 dp[0][i]=0;
30         }
31         for(int jn=m;jn>=1;jn--){    //必须把m的循环放外层,因为如果放里面需要再加个循环!这样就避免了完全背包问题多出的一个循环
32             for(int j=0;j<=10;j++){
33                 for(int i=1;i<=1000;i++){
34                     if(ak[jn].p<=j)continue;
35                     int aoe=ak[jn].p-j;
36                     if(aoe>=i){    //一击必杀的情况
37                         dp[i][j]=min(dp[i][j],ak[jn].k);
38                     }else{   
39                         dp[i][j]=min(dp[i][j],dp[i-aoe][j]+ak[jn].k);
40                     }
41                 }
42             }
43         }
44         long long sum=0;
45         int tmp;
46         bool flag=true;
47         for(int i=1;i<=n;i++){
48             tmp=dp[num[i].a][num[i].b];
49             if(tmp==INF){
50                 flag=false;
51                 break;
52             }
53             sum+=tmp;
54         }
55         if(!flag) cout<<-1<<endl;
56         else cout<<sum<<endl;
57     }
58     return 0;
59 }

 

2017百度之星资格赛1003 度度熊与邪恶大魔王