百度之星 资格赛 1003 度度熊与邪恶大魔王 dp(背包)

度度熊与邪恶大魔王

 
 Accepts: 1141
 
 Submissions: 6840
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 32768/32768 K (Java/Others)
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

一道完全背包的变形

这里贴出关键代码(dp部分)

比赛完贴完全代码

for(int i=0;i<=10;i++){
            dp[0][i] = 0;
            for(int j=1;j<=m;j++){
                ll tmp = sr[j].power - i;
                if(tmp<=0){
                    continue;
                }
                for(int k=tmp;k<=1009;k++){
                    dp[k][i] = min(dp[k][i],dp[k-tmp][i]+sr[j].value);
                }//i为防御值,k为生命值
            }
            for(int j=1008;j>=0;j--){
                dp[j][i] = min(dp[j][i],dp[j+1][i]);//确保当前防御值,生命值下消耗晶石最少
            }
        }

完整代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<cmath>
#define ls (u<<1)
#define rs (u<<1|1)
#define maxn 100010
#define ll long long
#define INF 1e18+7
using namespace std;
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
struct monster{
    ll life,defense;
};
struct store{
    ll value,power;
};
monster ms[maxn];
store sr[maxn];
ll dp[1010][15];
int main(){
    int n,m;
    while(cin >> n >> m){
        for(int i=0;i<=1009;i++){
            for(int j=0;j<=10;j++){
                dp[i][j] = INF;
            }
        }
        for(int i=1;i<=n;i++){
            cin >> ms[i].life >> ms[i].defense;
        }
        for(int i=1;i<=m;i++){
            cin >> sr[i].value >> sr[i].power;
        }
        for(int i=0;i<=10;i++){
            dp[0][i] = 0;
            for(int j=1;j<=m;j++){
                ll tmp = sr[j].power - i;
                if(tmp<=0){
                    continue;
                }
                for(int k=tmp;k<=1009;k++){
                    dp[k][i] = min(dp[k][i],dp[k-tmp][i]+sr[j].value);
                }
            }
            for(int j=1008;j>=0;j--){
                dp[j][i] = min(dp[j][i],dp[j+1][i]);
            }
        }
        ll ans = 0;
        for(int i=1;i<=n;i++){
            ans += dp[ms[i].life][ms[i].defense];
        }
        if(ans >= INF){
            cout << "-1" << endl;
        }
        else cout << ans << endl;
    }
    return 0;
}
Close
彼时当年少,莫负好时光。
原文地址:https://www.cnblogs.com/l609929321/p/7290602.html