2017"百度之星"程序设计大赛 - 资格赛-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

 

 

 

 

既然这个资格赛都没结束就有一大堆题解那我也水一发好了_(:з」∠)_

//这应该也是我唯一一道A得起的题了....然而还是看了某Na2O同学的分析.

------------以下为该同学的分析------------

 

所有人看见这个b的范围估计都很方吧

居然只有10

而且a[i]的范围也不大

所以这道题就是做b[i]次背包

把所有怪兽按照各自的b值分类

a[i]<=1000诶 m<=1000诶

对于第i类,背包的总容量为1000,每个怪兽都在自己的容量处打一个标记,做完全背包,最后每个容量的dp值,再乘上标记总数,加到答案中

怪不得那么多人过

 


------------------分析结束-------------------

 

然而,在WA了7次之后才AC的经历告诉我,这道题实在是有坑...

1.这道题要用long long(第7次WA之后改成了long long然后就AC了)

2.要考虑防御值为0的情况

3.一定要看清输入的意思....(否则很尴尬的..后面代码先输入p再输入k的事情就是看反了然后....各位凑合着看吧)

4.输出用I64d...其实交了lld也不会太碍事,好像有个窗口提示...

下为代码。

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,a[100005],b[100005],k[1005],p[1005],tag[1005],bs[15],dp[2020];
long long ans;
struct nde
{
    int a,b;
}c[100005];
bool cmp(nde p,nde q)
{
    if(p.b!=q.b) return p.b<q.b;
    return p.a<q.a;
}
int main()
{
    int i,j,l,lst;
    c[0].b=-1;
    while(~scanf("%d%d",&n,&m))
    {
        ans=0;
        memset(bs,0,sizeof(bs));
        for(i=1;i<=n;i++) scanf("%d%d",&c[i].a,&c[i].b);
        for(i=1;i<=m;i++) scanf("%d%d",&p[i],&k[i]);
        sort(c+1,c+n+1,cmp);
        for(i=1;i<=n;i++) if(c[i].b!=c[i-1].b) bs[c[i].b]=i;
        for(l=0;l<=10;l++)
        {
            if(!bs[l]) continue;
            memset(tag,0,sizeof(tag));memset(dp,0x3f,sizeof(dp));
            dp[0]=0;
            for(i=bs[l];c[i].b==l&&i<=n;i++) tag[c[i].a]++;
            lst=i-1;
            for(i=1;i<=m;i++)
                for(j=1;j<=c[lst].a;j++)
                    if(j-k[i]+l<0) dp[j]=min(dp[j],dp[0]+p[i]);
                    else dp[j]=min(dp[j],dp[j-k[i]+l]+p[i]);
            for(i=1;i<=c[lst].a;i++)
            {
                if(tag[i]&&dp[i]==0x3f3f3f3f) {ans=-1;break;}
                ans+=1ll*dp[i]*tag[i];
            }
            if(ans==-1) break;
        }
        printf("%I64d\n",ans);
    }
}


论一个日常翘掉自习上机房的我.【还有20天左右才放假然后开学

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值