首页 > 代码库 > 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
对于每组测试数据,输出最小的晶石消耗数量,如果不能击败所有的怪兽,输出-1Sample Input
1 2
3 5
7 10
6 8
1 2
3 5
10 7
8 6
Sample Output
6
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 度度熊与邪恶大魔王