百度之星1003 度度熊与邪恶大魔王

度度熊与邪恶大魔王

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 td=0; td<=maxd; td++) {
    for(int i=1; i<=maxHP; i++) {
        long long t = 0;
        bool flag=true;
        for(int j=0; j<m; j++) {
            if(ski[j].att<=0)continue;
            if(i-ski[j].att<=0) {
                if(t>ski[j].spend||flag) {
                    t=ski[j].spend;
                    flag = false;
                }
            } else if(flag||t>spe[i-ski[j].att][td]+ski[j].spend) {
                t=spe[i-ski[j].att][td]+ski[j].spend;
                flag = false;
            }
        }
        spe[i][td]=t;
    }
    for(int i=0; i<m; i++) ski[i].att--;
}

赛后更新



根据题目的意思 可以用完全背包解决 ,然后看题目给出的数据大小,可以在计算时计算生命值从1-1000,防御值0-10的所有情况,然后将所有符合对应的情况的怪兽加起来,之后就得出了消耗的水晶数。

#include<bits/stdc++.h>
#define MAX 1050

using namespace std;
int n,m;
long long int spe[MAX][11];//
long long int num[MAX][11];//每种情况对应的怪兽数量num[100][2]为生命值是100 防御力为2的怪兽的数量
long long int ans;
struct skill {
    int att,spend;
} ski[MAX];

int main() {
    while(cin>>n>>m) {
        ans=0;
        memset(num,0,sizeof(num));
        memset(spe,0,sizeof(spe));
        int maxa=0,maxd=0,maxHP=0,a,b,k,p;
        for(int i=0; i<n; i++) {
            cin>>a>>b;
            num[a][b]++;
            maxHP = max(maxHP,a);
            maxd = max(maxd,b);//记录生命值和防御力的最大值
        }
        for(int i=0; i<m; i++) {
            cin>>k>>p;
            ski[i].spend=k;
            ski[i].att=p;
            maxa = max(maxa,ski[i].att);//记录技能伤害的最大值
        }
        if(maxa<=maxd) {//技能伤害的最大值如果比防御力小则一定不能全部消灭,直接进行下一轮
            cout<<-1<<endl;
            continue;
        }
        for(int td=0; td<=maxd; td++) {
            for(int i=1; i<=maxHP; i++) {//枚举所有情况 只需判断生命值小于最大值、防御力小于最大值的即可
                long long t = 0;
                bool flag=true;
                for(int j=0; j<m; j++) {//完全背包
                    if(ski[j].att<=0)continue;
                    if(i-ski[j].att<=0) {
                        if(t>ski[j].spend||flag) {
                            t=ski[j].spend;
                            flag = false;
                        }
                    }else if(flag||t>spe[i-ski[j].att][td]+ski[j].spend) {
                        t=spe[i-ski[j].att][td]+ski[j].spend;
                        flag = false;
                    }
                }
                spe[i][td]=t;
            }
            for(int i=0;i<m;i++) ski[i].att--;//每次防御相同的怪兽枚举完时,将攻击力减少1 其实就是相当于攻击被防御抵消掉一部分
        }
        for(int i=0; i<=maxHP; i++) {
            for(int j=0; j<=10; j++) {
                ans+=(spe[i][j]*num[i][j]);//将所有的消耗累加
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值