度度熊与邪恶大魔王
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天左右才放假然后开学