/*
解题思路是:首先这个人有各种钱币,每种钱币若干,所以我们对这个人的钱用多重背包解决;
再者是找钱的人,可以认为他们有各种各样的钱币,都是无限件,所以对于收银员进行完全背包处理;
还有就是处理二者之间的关系 dp[i]表示支付i元钱至少多少张纸币,dp2[i-T]表示:收银员要找的钱的张数
两者相加即是所需要的张数,然后取最小值:
*/
# include<stdio.h>
# include<algorithm>
# include<string.h>
using namespace std;
# define inf 100000000
int dp1[20010],dp2[20010];
void CompletePack(int v)
{
for(int i=v; i<=20000; i++)
{
dp1[i]=min(dp1[i],dp1[i-v]+1);
}
}
void ZeroOnePack(int k,int v)
{
v=k*v;
for(int i=20000; i>=v; i--)
dp1[i]=min(dp1[i],dp1[i-v]+k);
}
void MultiplePack(int v,int num)
{
if(v*num>=20000)
{
CompletePack(v);
return ;
}
int k=1;
while(k<num)
{
ZeroOnePack(k,v);
num-=k;
k*=2;
}
ZeroOnePack(num,v);
}
int main()
{
int n,i,j,T;
int cas=0;
int v[110],num[110];
while(~scanf("%d%d",&n,&T),n+T)
{
for(i=1; i<=n; i++)
scanf("%d",&v[i]);
for(i=1; i<=n; i++)
scanf("%d",&num[i]);
for(i=1; i<=20000; i++)
dp1[i]=inf;
dp1[0]=0;
for(i=1; i<=n; i++)
MultiplePack(v[i],num[i]);
for(i=1; i<=20000; i++)
dp2[i]=inf;
dp2[0]=0;
for(i=1; i<=n; i++)
for(j=v[i]; j<=20000; j++)
dp2[j]=min(dp2[j],dp2[j-v[i]]+1);
int ans=inf;
for(i=T; i<=20000; i++)
{
ans=min(ans,dp1[i]+dp2[i-T]);
}
if(ans==inf)
ans=-1;
printf("Case %d: %d\n",++cas,ans);
}
return 0;
}
hdu 3591The trouble of Xiaoqian (多重背包)
最新推荐文章于 2020-03-25 11:05:03 发布