标签:sum 建立 sele mil back 数组 return sam pre
Problem:
度度熊为了拯救可爱的公主,于是与邪恶大魔王战斗起来。
邪恶大魔王的麾下有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 Out
6
18
问题如上。
不用完全背包求最小晶石消耗数量:
1 #define min(a, b) (a) < (b) ? (a) : (b) 2 3 class Solution 4 { 5 public: 6 int dudubear(vector<int> life, vector<int> defense, vector<int> star, vector<int> attack, int n, int m) 7 { 8 int rightMinValue = 100000, leftMinValue = 100000, sum = 0; 9 vector<int> selectValue; 10 vector<int> newselectValue; 11 12 for (int i = 0; i < n; ++i) 13 { 14 for (int j = 0; j < m; ++j) 15 { 16 if (attack[j] >= life[i] + defense[i]) 17 { 18 rightMinValue = min(star[j], rightMinValue); 19 continue; 20 } 21 if ((attack[j] > defense[i]) && (attack[j] < defense[i] + life[i])) 22 { 23 selectValue.push_back(j); 24 continue; 25 } 26 if (j == m - 1) 27 { 28 return -1; 29 } 30 } 31 //因为技能可重复使用,但单个技能重复使用累加起来的伤害(攻击-防御)超过怪兽的生命值时无意义 32 //所以每个技能的使用次数不能超过(life[i] / (attack[selectValue[j]] - defense[i]))+1 33 //建立新数组,储存单个技能使用最大次数的数组 34 int count = 0; 35 for (int j = 0; j < selectValue.size(); ++j) 36 { 37 int items = (life[i] / (attack[selectValue[j]] - defense[i])) + 1; 38 for (int k = 0; k < items; ++k) 39 { 40 newselectValue.push_back(selectValue[j]); 41 ++count; 42 } 43 } 44 45 46 int flag = 4; 47 int bitcount = 2; 48 for (int j = 3; j <= ((int)pow(2, count)) - 1; ++j) 49 { 50 if (j == flag) 51 { 52 flag = flag << 1; 53 ++bitcount; 54 continue; 55 } 56 //计算当前情况所耗费晶石数量 57 int sumDamage = 0, sumStar = 0; 58 for (int k = 1; k < bitcount + 1; ++k) 59 { 60 if ((j >> (k - 1) & 1) == 1) 61 { 62 sumDamage += attack[newselectValue[count - k]] - defense[i]; 63 sumStar += star[newselectValue[count - k]]; 64 } 65 } 66 if (sumDamage < life[i]) 67 continue; 68 if (sumStar > rightMinValue) 69 continue; 70 leftMinValue = min(sumStar, leftMinValue); 71 } 72 leftMinValue == 100000 ? sum += rightMinValue : sum += leftMinValue; 73 leftMinValue = 100000; 74 rightMinValue = 100000; 75 selectValue.clear(); 76 newselectValue.clear(); 77 } 78 79 return sum; 80 } 81 };
标签:sum 建立 sele mil back 数组 return sam pre
原文地址:http://www.cnblogs.com/yeqingqian/p/7668377.html