度度熊与邪恶大魔王
Accepts: 2016
Submissions: 12307
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
度度熊为了拯救可爱的公主,于是与邪恶大魔王战斗起来。
邪恶大魔王的麾下有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
Sample Output
8
16
Aceppted代码
/*
Problem:度度熊与邪恶大魔王
Author:QiZhao
Data:2017-08-05
Description:DP,完全背包
Copyright 2017 QiZhao. All rights reserved.
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1020;
const ll INF=0x3f3f3f3f;
ll num[maxn][12];//防御值为j,生命值为i的怪物的个数
ll dp[1020][15];//对于生命值为i,防御值为j的怪物所消耗的最小水晶数
struct skill
{
ll hit;
ll price;
} a[maxn];
ll best[maxn];//攻击力为i时,消耗的最少水晶数。
ll min(ll a,ll b)
{
if(a>b)
return b;
else
return a;
}
void complete_packet(int k, int p)//p为攻击力,k为消耗水晶数
{
for (int b = 0; b <= 10; ++b)
{
if (b >= p)
{
continue;
}
else
{
int d = p - b;
//血量小于攻击
for (int a = 1; a <= d; ++a)
{
dp[a][b] = min(dp[a][b], k);
}
//血量大于攻击
for (int a = d + 1; a <= 1000; ++a)
{
dp[a][b] = min(dp[a][b], dp[a - d][b] + k);
}
}
}
}
int main()
{
cin.sync_with_stdio(false);
ll n, m;
ll x, y;
ll /*max_hp = -0xffff,*/ max_def = -INF, max_hit = -INF;
while(cin >> n >> m)
{
max_def = -INF, max_hit = -INF;
memset(num, 0, sizeof(num));
memset(a, 0, sizeof(a));
memset(best, -1, sizeof(best));
memset(dp, 0, sizeof(dp));
for(ll i = 0; i < n; i++)
{
cin >> x >> y;
num[x][y]++;
//if(x >= max_hp)
//max_hp = x;
if(y >= max_def)
max_def = y;
}
ll flag = 0;
for(ll i = 0; i < m; i++)
{
cin >> x >> y;
if(best[y] == -1)
{
a[flag].hit = y;
a[flag].price = x;
best[y] = x;
if(a[flag].hit > max_hit)
max_hit = a[flag].hit;
flag++;
}
else
{
if(x < best[y])
best[y] = x;
}
}
ll ans = 0;
ll temp = 0; //记录已处理怪物个数,优化时间
if(max_def >= max_hit)
cout << "-1" << endl;
else
{
for (int i = 0; i <= 1010; ++i)//初始化DP
{
for (int j = 0; j <= 10; ++j)
{
if (i == 0)
{
dp[i][j] = 0;
}
else
{
dp[i][j] = INF;
}
}
}
for(int i=0;i<flag;i++)
complete_packet(best[a[i].hit],a[i].hit);
for(ll i = 0; i < 1002; i++)
{
if(temp == n)//优化时间
break;
for(ll j = 0; j < 12; j++)
{
if(num[i][j] != 0)
{
temp += num[i][j];
ans += dp[i][j]*num[i][j];
}
}
}
cout << ans << endl;
}
}
return 0;
}