度度熊与邪恶大魔王
Accepts: 845
Submissions: 5001
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
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
1 2 3 5 7 10 6 8 1 2 3 5 10 7 8 6
Sample Output
6 18
枚举每一种防御,然后暴力求出每种血量的最小花费,a[i][j]表示血量为i防御为j的人的数量,因此对于每个
a[i][j],ans=min(dp[j][i],dp[j][i+1]....dp[j][1000])*a[i][j],最后所有答案求和即可。
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; #define __int64 long long const int maxm = 1000005; const __int64 INF = 1e15; struct node { int h; __int64 w; bool operator<(const node &r)const { return w < r.w; } }f[20005]; int a[20005][15] = { 0 }, n, m, p[maxm]; __int64 dp[2005], k[maxm]; void find(int cnt); int main() { int i, j, sum, x, y, r, flag, cnt; __int64 ans, rev, xx; while (scanf("%d%d", &n, &m) != EOF) { memset(a, 0, sizeof(a)); for (i = 1;i <= n;i++) { scanf("%d%d", &x, &y); a[x][y]++; } for (i = 1;i <= m;i++) scanf("%I64d%d", &k[i], &p[i]); flag = 1;ans = 0; for (j = 0;j <= 10;j++) { cnt = 0; for (r = 1;r <= m;r++) { if (p[r] - j <= 0) continue; f[++cnt].h = p[r] - j; f[cnt].w = k[r]; } find(cnt); rev = INF; for (i = 1000;i >= 1;i--) { rev = min(rev, dp[i]); if (a[i][j] > 0) { if (rev == INF) { flag = 0;break; } ans += (__int64)(rev*a[i][j]); } } if (flag == 0) break; } if (flag == 0) printf("-1\n"); else printf("%I64d\n", ans); } return 0; } void find(int cnt) { memset(dp, 1, sizeof(dp)); for (int i = 1;i <= cnt;i++) dp[f[i].h] = min(dp[f[i].h], f[i].w); for (int i = 1;i <= 1000;i++) { for (int j = 1;j <= cnt;j++) { dp[i + f[j].h] = min(dp[i + f[j].h], dp[i] + f[j].w); if (i + f[j].h >= 1000) dp[1000] = min(dp[1000], dp[i + f[j].h]); } } }