度度熊与邪恶大魔王Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 180 Accepted Submission(s): 84
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
Sample Output
Source
|
给出的防御值和攻击值都比较小,可以先枚举防御值,然后,把血量和攻击值及其对应的宝石处理成完全背包问题,把血量当成背包去装攻击值(别忘了让攻击值预先减去枚举的防御值),使附带的是宝石尽可能少。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define max_n 100010
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
LL dp[1005][12];
LL a[max_n], b[max_n], k[max_n], p[max_n];
int main() {
LL p1, p2, n, m;
while(scanf("%lld %lld", &n, &m) != EOF) {
LL maxn1 = 0, maxn2 = 0;
for(LL i = 0; i < n; i++) {
scanf("%lld %lld", &a[i], &b[i]);
maxn1 = max(maxn1, b[i]);
}
for(LL i = 0; i < m; i++) {
scanf("%lld %lld", &k[i], &p[i]);
maxn2 = max(maxn2, p[i]);
}
if(maxn2 <= maxn1) { //特判一下,最大攻击值不大于防御值
printf("-1\n");
continue;
}
memset(dp, INF, sizeof(dp));
for(LL i = 0; i <= 10; i++) {
for(LL v = 1; v < 1005; v++) { //枚举血量
for(LL j = 0; j < m; j++) { //枚举攻击值,处理成完全背包
LL res = p[j] - i;
if(res <= 0) continue;
if(res >= v) dp[v][i] = min(dp[v][i], k[j]); //分情况
else dp[v][i] = min(dp[v][i], dp[v - res][i] + k[j]);
}
}
}
LL ans = 0;
for(LL i = 0; i < n; i++) {
ans += dp[a[i]][b[i]];
}
printf("%lld\n", ans);
}
return 0;
}