具体内容见背包九讲(3)
相关题目:hdu 1171 2844 1059/poj1014 2191 (没做:poj 2392 poj1276)
hdu 2844
大意:有不同价值的硬币,每种价值硬币有一定数量个。求用这些硬币可以组成的钱的种数是多少。
则判断条件不在是 :if( f[i] < f[i-v] + w) ··· 而是 if(f[i] == 0 && f[i - v] != 0) sum++
代码:
//是求可能组成<m的钱数的可能数 #include<iostream> #include<string.h> #define size 100010 using namespace std; int f[size]; int n,m,sum; void ZeroOnePack(int v) { for(int i=m;i>=v;i--) if(f[i]==0 && f[i-v]!=0) f[i]=1,sum++; } void MultiplePack(int v,int no) { if(v*no>=m) { for(int i=v;i<=m;i++) if(f[i]==0 && f[i-v]!=0) f[i]=1,sum++; } else { int k=1; while(k<no) { ZeroOnePack(k*v); no-=k; k*=2; } ZeroOnePack(no*v); } return; } int main() { int v[110],no[110]; while(scanf("%d%d",&n,&m)!=EOF && n && m) { for(int i=0;i<n;i++) scanf("%d",&v[i]); for(int i=0;i<n;i++) scanf("%d",&no[i]); memset(f,0,sizeof(f)); f[0]=1; sum=0; for(int i=0;i<n;i++) { MultiplePack(v[i],no[i]); } printf("%d\n",sum); } return 0; }
#include<iostream> #include<string.h> using namespace std; int f[110]; int v[110],w[110],no[110]; int n,m; void ZeroOnePack(int v,int w) { for(int i=n;i>=v;i--) if(f[i]<f[i-v]+w) f[i] = f[i-v]+w; } void MultiplePack(int v,int w,int no) { if(v*no>=n) { for(int i=v;i<=n;i++) if(f[i]<f[i-v]+w) f[i] = f[i-v]+w; } int k=1; while(k<no) { ZeroOnePack(v*k,k*w); no-=k; k*=2; } ZeroOnePack(v*no,no*w); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(f,0,sizeof(f)); for(int i=0;i<m;i++) { scanf("%d%d%d",&v[i],&w[i],&no[i]); } for(int i=0;i<m;i++) MultiplePack(v[i],w[i],no[i]); int max=0; for(int i=n;i>=0;i--) if(f[i]>max) max=f[i]; printf("%d\n",max); } return 0; }