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

xiaoxiao2021-02-28  102

 

度度熊与邪恶大魔王

 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天左右才放假然后开学

 

转载请注明原文地址: https://www.6miu.com/read-43189.html

最新回复(0)