/* ans[i][j][b]表示防御力为b的怪物 表示用前i种技能,造成恰好j的伤害消耗的最小晶石 ans[i][j][b]=min{ans[i-1][j-x*(p[i]-b)]+x*k[i]} x表示第i种技能取x个(0<=x*(p[i]-b)<=j) 优化:http://blog.csdn.net/wumuzi520/article/details/7014830 ans[i][j][b]=min(ans[i-1][j][b],ans[i][j-(p[i]-b)][b]+k[i]【j>=p[i]-b】) =>ans[j][b]=min(ans[j][b],ans[j-(p[i]-b)][b]+k[i] **i从小到大 */ #include #include #include using namespace std; typedef long long LL; LL n,m; LL maxb,maxp,bx,maxa; LL a[100100],b[100100]; LL ans[10001][11]; LL k[1010],p[1010],ans1; int main() { LL i,j,t,ze=(long long)0; while(scanf("%lld%lld",&n,&m)==2) { maxb=0;maxp=0;maxa=0; for(i=1;i<=n;i++) { scanf("%lld%lld",&a[i],&b[i]); maxb=max(maxb,b[i]); maxa=max(maxa,a[i]); } for(i=1;i<=m;i++) { scanf("%lld%lld",&k[i],&p[i]); maxp=max(maxp,p[i]); } maxa=max(maxa,maxp); /* 去掉以上这句,会让类似 1 1 45 10 4164 327 的数据得出错误结果 */ if(maxb>=maxp) { printf("-1\n"); continue; } memset(ans,0x3f,sizeof(ans)); memset(ans[0],0,sizeof(ans[0])); for(bx=0;bx<=maxb;bx++) { for(i=1;i<=m;i++) for(j=max(ze,p[i]-bx);j<=2*maxa;j++) // { //if(j>=p[i]-bx) ans[j][bx]=min(ans[j][bx],ans[j-p[i]+bx][bx]+k[i]); // } t=0x3f3f3f3f; for(j=2*maxa;j>=0;j--) { t=min(t,ans[j][bx]); ans[j][bx]=min(ans[j][bx],t); } } ans1=0; for(i=1;i<=n;i++) ans1+=ans[a[i]][b[i]]; printf("%lld\n",ans1); } return 0; }