一个多重背包问题,有一点儿不同的是状态转移方程式了,这里的dp存的不再是价值和了,而是一个bool值,代表的是dp[i]中能不能凑齐到i 的钱,和01背包很像,说明如下:
假如现在要新添一个银币j,问是否能够凑齐到钱 i .那么,如果现在需要凑齐的钱i 减去 硬币 j 的面值 的钱 为 i-A[j].cost,如果i-A[j].cost的钱依然能够凑齐,那么i 也必定能凑齐(这个不用解释吧)
dp[i]=dp[i-A[j].cost]?true:false
然后就一样了
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAX =100005;
bool dp[MAX];
int v;
int a[MAX],num[MAX];
void zeroOnePack(int cost ,int value)
{
for(int i=v;i>=cost;i--)
if(dp[i-cost]==true)
dp[i]=true;
}
void completePack(int cost,int value)
{
for(int i=cost;i<=v;i++)
if(dp[i-cost]==true)
dp[i]=true;
}
void multiplePack(int cost,int value,int amount)
{
if(cost*amount>=v)
{
completePack(cost,value);
return ;
}
int k=1;
while(k<amount)
{
zeroOnePack(k*cost,k*value);
amount-=k;
k*=2;
}
zeroOnePack(amount*cost,amount*value);
}
int main()
{
int n;
while(~scanf("%d%d",&n,&v),v,n)
{
memset(dp,false,sizeof(dp));
dp[0]=true;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
for(int i=1;i<=n;i++)
multiplePack(a[i],1,num[i]);
int cnt=0;
for(int i=1;i<=v;i++)
if(dp[i])
cnt++;
printf("%d\n",cnt);
}
return 0;
}