标签:blog io sp for on 2014 log bs amp
给出N种钱币和M
给出N种钱币的面值和个数
NPC拿着这N些钱币去买价值M的物品,可以多付,然后被找零,找零的钱也为这些面值,但没有数量限制
问最少经手的钱币数量
对于NPC做一个付款多重背包
然后对于找零做一个完全背包
ans=Min(dp1[i]+dp2[i-m],ans);
#include "stdio.h"
#include "string.h"
int n,m;
int dp1[20010],dp2[20010],c[20010],v[20010];
void onezero_pack(int v,int k)
{
int i;
for (i=20000;i>=v;i--)
if (dp1[i-v]!=-1 && (dp1[i-v]+k<dp1[i] || dp1[i]==-1) )
dp1[i]=dp1[i-v]+k;
}
void complete_pack(int v)
{
int i;
for (i=v;i<=20000;i++)
if (dp1[i-v]!=-1 && (dp1[i-v]+1<dp1[i] || dp1[i]==-1) )
dp1[i]=dp1[i-v]+1;
}
void multiple_pack(int v,int c)
{
int k;
if (v*c>=20000)
complete_pack(v);
else
{
k=1;
while (k<c)
{
onezero_pack(k*v,k);
c-=k;
k*=2;
}
if (c>0) onezero_pack(c*v,k);
}
}
int Min(int a,int b)
{
if (a<b) return a;
else return b;
}
int main()
{
int Case,i,j,ans;
Case=0;
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n+m==0) break;
for (i=1;i<=n;i++)
scanf("%d",&v[i]);
for (i=1;i<=n;i++)
scanf("%d",&c[i]);
memset(dp1,-1,sizeof(dp1));
dp1[0]=0;
for (i=1;i<=n;i++)
multiple_pack(v[i],c[i]);
memset(dp2,-1,sizeof(dp2));
dp2[0]=0;
for (i=1;i<=n;i++)
for (j=0;j<=20000-v[i];j++)
{
if (dp2[j]!=-1 && (dp2[j]+1<dp2[j+v[i]] || dp2[j+v[i]]==-1) )
dp2[j+v[i]]=dp2[j]+1;
}
ans=0x3f3f3f3f;
for (i=m;i<=20000;i++)
if (dp1[i]!=-1 && dp2[i-m]!=-1)
ans=Min(dp1[i]+dp2[i-m],ans);
printf("Case %d: ",++Case);
if (ans==0x3f3f3f3f)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}
标签:blog io sp for on 2014 log bs amp
原文地址:http://blog.csdn.net/u011932355/article/details/41253563