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代码:ps:昨天晚上贴的代码是wa 的,我贴错了,尴尬。。。

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #include<string.h>
 5 #include<string.h>
 6 using namespace std;
 7 const int INF=0x3f3f3f3f;    //这样表示的INF才能在memset函数中使用
 8 struct Node{
 9     int a,b;
10 }num[100050];
11 struct Node2{
12     int p,k;
13 }ak[1005];
14 int dp[1005][15];   //用二维数组,之前用三维内存超限
15 int main(){
16     int n,m;
17     while(~scanf("%d%d",&n,&m))
18     {
19         int mmxx=0;
20         for(int i=1;i<=n;i++){
21             scanf("%d %d",&num[i].a,&num[i].b);
22             mmxx=max(mmxx,num[i].b);
23         }
24         int mx=0;
25         for(int i=1;i<=m;i++){
26             scanf("%d %d",&ak[i].k,&ak[i].p);
27             mx=max(mx,ak[i].p);
28         }
29         if(mmxx>=mx){
30             cout<<-1<<endl;
31             continue;
32         }
33         memset(dp,INF,sizeof(dp));
34         for(int i=0;i<15;i++){
35                 dp[0][i]=0;
36         }
37         for(int jn=m;jn>=1;jn--){  //这层循环放外层!
38             for(int j=0;j<=10;j++){
39                 for(int i=1;i<=1000;i++){
40                     if(ak[jn].p<=j)continue;
41                     int aoe=ak[jn].p-j;
42                     if(aoe>=i){    //一击必杀
43                         dp[i][j]=min(dp[i][j],ak[jn].k);
44                     }else{
45                         dp[i][j]=min(dp[i][j],dp[i-aoe][j]+ak[jn].k);
46                     }
47                 }
48             }
49         }
50         long long sum=0;
51         for(int i=1;i<=n;i++){
52             sum+=dp[num[i].a][num[i].b];
53         }
54         cout<<sum<<endl;
55     }
56     return 0;
57 }
原文地址:https://www.cnblogs.com/ISGuXing/p/7296326.html