这个题是说给你n种金币的面额以及他们的数量,并给你一个金额T,让你进行一个购物拿钱的计算,自己拿出的钱有数量限制,店主找钱的话则没有数量限制,让你算出要成功购买T元的东西至少需要拿出多少张钱。
由上述所说,自己拿出钱是一个多重背包,而店主找钱则是一个完全背包,进行相应的做即可
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=25010;
struct node
{
int num;
int val;
}a[11010];
int n,cur,m,v[110],c[110],dpa[maxn],dpb[maxn];
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(dpb,0x3f,sizeof(dpb));
memset(dpa,0x3f,sizeof(dpa));
dpa[0]=dpb[0]=0;
int mx=0;
for(int i=0;i<n;i++)
{
scanf("%d",&v[i]);
mx=max(mx,v[i]);
}
mx*=mx;
cur=0;
for(int i=0;i<n;i++)
{
scanf("%d",&c[i]);
for(int j=0;(1<<j)<=c[i];j++)
{
a[cur++]=(node){1<<j,(1<<j)*v[i]};
c[i]-=1<<j;
}
if(c[i]>1)
a[cur++]=(node){c[i],c[i]*v[i]};
}
for(int i=0;i<n;i++)
for(int j=v[i];j<=mx;j++)
dpa[j]=min(dpa[j],dpa[j-v[i]]+1);
for(int i=0;i<cur;i++)
for(int j=mx;j>=a[i].val;j--)
dpb[j]=min(dpb[j],dpb[j-a[i].val]+a[i].num);
int ans=0x7f7f7f7f;
for(int i=m;i<=mx;i++)
ans=min(ans,dpb[i]+dpa[i-m]);
printf("%d\n",ans==0x7f7f7f7f?-1:ans);
}
return 0;
}