【背包模板】
来源:互联网 发布:net编程教训 编辑:程序博客网 时间:2024/05/17 22:40
int V;//容量 //01void zeroone(int cost,int val){//费用,价值 int i; for(i=V;i>=cost;i--){ if(dp[i]<dp[i-cost]+val){ dp[i] = dp[i-cost]+val; } } } //完全背包void complete(int cost,int val){//费用,价值 int i; for(i=cost;i<=V;i++){ if(dp[i]<dp[i-cost]+val){ dp[i] = dp[i-cost]+val; } } } //多重背包void multi(int cost,int val,int cnt){//费用,价值,数量 if(cost*cnt>=V){ complete(cost,val); return ; } int k = 1; while(k<cnt){ zeroone(k*cost,k*val); cnt -= k; k *= 2; } zeroone(cnt*cost,cnt*val); } //混合三种背包:for(i=0;i<m;i++){ scanf("%d%d%d%d",&v,&weight,&value,&n); if(v>V || weight>W) continue; if(n==1) zeroone(v,weight,value); else if(n==0) complete(v,weight,value); else multiply(v,weight,value,n);}//二维费用的背包:void zeroone(int v,int weight,int value){ int i,j; for(i=V;i>=v;i--) for(j=W;j>=weight;j--) if(dp[i][j]<dp[i-v][j-weight]+value) dp[i][j]=dp[i-v][j-weight]+value;}void complete(int v,int weight,int value){ int i,j; for(i=v;i<=V;i++) for(j=weight;j<=W;j++) if(dp[i][j]<dp[i-v][j-weight]+value) dp[i][j]=dp[i-v][j-weight]+value;}void multiply(int v,int weight,int value,int count){ if(v*count>=V || weight*count>=W){ complete(v,weight,value); return; } int k=1; while(k<count){ zeroone(k*v,k*weight,k*value); count-=k; k*=2; } zeroone(count*v,count*weight,count*value);}//分组背包:for(i=1;i<=n;i++){ //枚举组 for(j=m;j>=1;j--){ //背包容量 for(k=1;k<=m;k++){ //不同费用的物品 if(j>=k) //转移方程有j-k,要保证j-k>=0 dp[j] = max(dp[j],dp[j-k]+a[i][k]); } }}