题目

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

knzeus
72 声望28 粉丝

行万里路,读万卷书