多重背包。。。
所有的背包,感觉都以01背包为基础,所以。。不懂多用数据,多模拟。。就懂了
1.未经优化版本,先理解这个,二进制只是把这个改进了一下而已
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; int main() { int f[12005]; int num[7],v; freopen("in.txt","r",stdin); for(int t=1;;t++) { memset(f,0,sizeof(f)); v=0; for(int i=1;i<=6;i++) { scanf("%d",&num[i]); v+=num[i]*i; } if(!v)break; printf("Collection #%d:\n",t); if(v%2)printf("Can't be divided.\n"); else { v=v/2; for(int i=1;i<=6;i++) { for(int j=1;j<=num[i];j++) { for(int k=v;k>=i;k--) { f[k]=f[k]>f[k-i]+i?f[k]:f[k-i]+i; } } } if(f[v]==v)printf("Can be divided.\n\n"); else printf("Can't be divided.\n\n"); } } return 0; }
背包九讲虽然些的好,毕竟纸上谈兵,感觉网上有的带表格,一步步走数据的方法结合起来学的更透彻
AC:
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; int tot; int f[120005],a[7]; void ZeroOnePack(int cost,int weight) { for(int v=tot;v>=cost;v--) { f[v]=f[v]>f[v-cost]+weight?f[v]:f[v-cost]+weight; } } void CompletePack(int cost,int weight) { for(int v=cost;v<=tot;v++) { f[v]=f[v]>f[v-cost]+weight?f[v]:f[v-cost]+weight; } } void MultiplePack(int cost,int weight,int amount) { if(cost*amount>=tot)CompletePack(cost,weight); else { for(int k=1;k<amount;k=k<<1) { ZeroOnePack(k*cost,k*weight); amount=amount-k; } ZeroOnePack(amount*cost,amount*weight); } } int main() { //freopen("in.txt","r",stdin); for(int t=1;;t++) { tot=0; for(int i=1;i<=6;i++) { scanf("%d",&a[i]); tot+=a[i]*i; } if(!tot)break; printf("Collection #%d:\n",t); if(tot%2)printf("Can't be divided.\n\n"); else { tot=tot/2;memset(f,0,sizeof(f)); for(int i=1;i<=6;i++) { MultiplePack(i,i,a[i]); } if(f[tot]==tot)printf("Can be divided.\n\n"); else printf("Can't be divided.\n\n"); } } return 0; }