题目
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
方案
防御力只有0-10一共11种场景,可以预先都计算出来,后续直接调用加和。
问题可以简化为对一个没有防御力的怪兽,最少需要多少晶石。
也就是一个完全背包问题了。
代码
/***************************************************************************
*
* Copyright (c) 2017 knzeus, Inc. All Rights Reserved
* $Id$
*
**************************************************************************/
/**
* @file src/main.cpp
* @author knzeus
* @date 2017/08/06 12:23:11
* @version $Revision$
* @brief
*
**/
#include <cstdlib>
#include <cstdio>
using namespace std;
struct Monster {
long long life;
long long defense;
};
struct Killer {
long long cost;
long long hurt;
};
int killer_cmp(const void* k1, const void* k2) {
const Killer* kl = (const Killer*)k1;
const Killer* kr = (const Killer*)k2;
if (kl->hurt < kr->hurt) {
return 1;
} else if (kl->hurt > kr->hurt) {
return -1;
}
if (kl->cost < kr->cost) {
return -1;
}
}
class MonsterMgr {
public:
void input(int n, FILE* fp) {
ms_num = n;
for (int i = 0; i < n; i++) {
Monster& m = ms[i];
fscanf(fp, "%lld %lld", &m.life, &m.defense);
}
}
Monster get(int i) const {
return ms[i];
}
int num() const {
return ms_num;
}
private:
Monster ms[100000];
int ms_num;
};
class KillerMgr {
public:
void input(int n, FILE* fp) {
ks_num = n;
for (int i = 0; i < n; i++) {
Killer& k = ks[i];
fscanf(fp, "%lld %lld", &k.cost, &k.hurt);
}
}
void init_cost() {
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 1008; j++) {
cost[i][j] = -1;
}
cost[i][0] = 0;
}
}
void dp() {
compress_killer();
init_cost();
for (int i = 0; i < 11; i++) {
dp(i);
dec();
}
}
void dec() {
for (int i = 0; i < ks_num; i++) {
ks[i].hurt--;
}
}
void dp(int i) {
for (int ki = 0; ki < ks_num; ki++) {
const Killer& k = ks[ki];
if (k.hurt <= 0) {
continue;
}
for (int j = 1; j < 1001; j++) {
int cnt_i = 0;
while (true) {
int last_j = j - cnt_i * k.hurt;
if (last_j + k.hurt <= 0 || cnt_i == 2) {
break;
}
int cur_cost = k.cost * cnt_i;
int last_j_cost;
if (last_j <= 0) {
last_j_cost = 0;
} else if (cost[i][last_j] == -1) {
cnt_i++;
continue;
} else {
last_j_cost = cost[i][last_j];
}
cur_cost += last_j_cost;
if (cur_cost < cost[i][j] || cost[i][j] == -1) {
cost[i][j] = cur_cost;
}
cnt_i++;
}
}
}
}
long long kill(Monster m) {
return cost[m.defense][m.life];
}
long long kill(const MonsterMgr& mm) {
dp();
long long res = 0;
for (int i = 0; i < mm.num(); i++) {
long long one_res = kill(mm.get(i));
if (one_res == -1) {
return -1;
}
res += one_res;
}
return res;
}
void compress_killer() {
qsort(&ks[0], ks_num, sizeof(Killer), killer_cmp);
int j = 0;
for (int i = 1; i < ks_num; i++) {
if (ks[i].hurt == ks[j].hurt) {
continue;
}
j++;
if (j != i) {
ks[j] = ks[i];
}
}
ks_num = j + 1;
}
private:
Killer ks[1001];
int ks_num;
long long cost[11][1008];
};
int main(int argc, char *argv[])
{
FILE* fp = stdin;
fp = fopen("./data/test.txt", "r");
int n, m;
while (true) {
if (EOF == fscanf(fp, "%d %d", &n, &m)) {
break;
}
MonsterMgr mm;
KillerMgr km;
mm.input(n, fp);
km.input(m, fp);
printf("%lld\n", km.kill(mm));
}
return 0;
}
/* vim: set ts=4 sw=4 sts=4 tw=100 */
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。