给出n个数和m
每个数给出出现次数和价值,问任意组合组成不大于M的价值,共能产生多少个数
多重背包的的二进制优化写法 模板mark一下
二进制优化原理:
1、2、4可以组合出所有小于8的数;
1、2、4、8可以组合出所有小于16的数;
1、2、4、8、16可以组合出所有小于32的数;
……
#include "stdio.h"
#include "string.h"
int n,m;
int dp[100010];
void complete_pack(int v)
{
int i;
for (i=v;i<=m;i++)
if (dp[i-v]==1) dp[i]=1;
}
void onezero_pack(int v)
{
int i;
for (i=m;i>=v;i--)
if (dp[i-v]==1) dp[i]=1;
}
void multiple_pack(int v,int c)
{
int k;
if (v*c>=m)
complete_pack(v);
else
{
k=1;
while (k<c)
{
onezero_pack(k*v);
c-=k;
k*=2;
}
onezero_pack(c*v);
}
}
int main()
{
int v[101],c[101];
int i,ans;
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(dp,0,sizeof(dp));
dp[0]=1;
for (i=1;i<=n;i++)
multiple_pack(v[i],c[i]);
ans=0;
for (i=1;i<=m;i++)
if (dp[i]!=0) ans++;
printf("%d\n",ans);
}
return 0;
}