Problem Description
度度熊为了拯救可爱的公主,因而与邪恶大魔王战斗起来。vim
邪恶大魔王的麾下有n个怪兽,每一个怪兽有a[i]的生命值,以及b[i]的防护力。测试
度度熊一共拥有m种攻击方式,第i种攻击方式,须要消耗k[i]的晶石,形成p[i]点伤害。spa
固然,若是度度熊使用第i个技能打在第j个怪兽上面的话,会使得第j个怪兽的生命值减小p[i]-b[j],固然若是伤害小于防护,那么攻击就不会奏效。code
若是怪兽的生命值降为0或如下,那么怪兽就会被消灭。ip
固然每一个技能均可以使用无限次。get
请问度度熊最少携带多少晶石,就能够消灭全部的怪兽。input
Input
本题包含若干组测试数据。it
第一行两个整数n,m,表示有n个怪兽,m种技能。io
接下来n行,每行两个整数,a[i],b[i],分别表示怪兽的生命值和防护力。ast
再接下来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 */