给出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; }
时间: 2024-10-10 04:39:57