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