您的位置:首页 > 其它

2017"百度之星"程序设计大赛 - 资格赛-1003-度度熊与邪恶大魔王

2017-08-06 12:03 381 查看


度度熊与邪恶大魔王

 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天左右才放假然后开学
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: