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 */