【百度之星2017】資格賽-題3-度度熊與邪惡大魔王

題目

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 */
相關文章
相關標籤/搜索