背包问题
背包问题(要不断更新)
一.01背包
Q:N物品,T容量,Wi消耗,Vi价值,每件物品取一个,怎样价值最大?(还记得在清北手推了二维的转移方程,但现在并不知道倒序的原理)
for(int i=1;i<=n;i++){//放到第i件物品 for(int j=T;j>=0;j--){//倒序,防止重复往里面放 if(j>=weight[i]){ dp[j]=max(dp[j],dp[j-weight[i]]+value[i]); } else{ dp[j]=dp[j]; } } }//dp[j]代表当容量为j时的最大价值
注意:倒序j
二.完全背包
Q:N物品,T容量,Wi消耗,Vi价值,每件物品取随意个,怎样价值最大?
for(int i=1;i<=n;i++){ for(int j=weight[i];j<=T;j++){ dp[j]=max(dp[j],dp[j-weight[i]]+value[i]); } }
注意:正序j
三.多重背包
Q:N物品,T容量,Wi消耗,Vi价值,每件物品取Ni个,怎样价值最大?
for(int i=1;i<=n;i++){ for(int j=T;j>=0;j--){ for(int k=0;k<=s[i];k++){ if(j-k*weight[i]<0)break; dp[j]=max(dp[j],dp[j-k*weight[i]]+k*value[i]); } } }
二进制优化还不会qaq一定要学会回头再编辑!
四.二维背包
Q:N物品,T1容量,T2容量,Wi1消耗,Wi2消耗,,Vi价值,每件物品取1个,怎样价值最大?
for(int i=1;i<=n;i++){ for(int j=T1;j>=v[i];j--){ for(int k=T2;k>=m[i];k--){ dp[j][k]=max(dp[j][k],dp[j-v[i]][k-m[i]]+value[i]); } } }
多加一维,多for一个量的01背包
五.混合背包
N物品,T容量,,Wi消耗,,V价值,有的物品取1个,有的物品取随意个,有的物品取s[i]个,怎样价值最大?(s[i]为0为随意)
for(int i=1;i<=n;i++){ if(s[i]==0){//完全 for(int j=weight[i];j<=T;j++){ dp[j]=max(dp[j],dp[j-weight[i]]+value[i]); } } else{//01,多重 for(int k=1;k<=s[i];k++){ for(int j=T;j>=weight[i];j--){ dp[j]=max(dp[j],dp[j-weight[i]]+value[i]) } } } }
六.分组背包
N组物品,每组只可以选一个,T容量,怎样取价值最大?
for(int i=1;i<=n;i++){ cin>>weight[i]>>value[i]>>x; t=max(t,x);//求组数 b[x]++;//这一组中的序号++ g[x][b[x]]=i;//组里第n个为第i个的信息 } for(int i=1;i<=t;i++){ for(int j=T;j>=0;j--){ for(int k=1;k<=b[i];k++){ if(j>=weight[g[i][k]]){ dp[j]=max(dp[j],dp[j-weight[g[i][k]]]+value[g[i][k]]); } } } }
多for组,再for容量,最后for每组的元素,注意预处理
七.有依赖性的背包
N物品,里面有主件也有附件,买附件就必须买主件,每个主件最多有两个附件,问怎样价值最大?
for(int i=1;i<=n;i++){ cin>>m>>v>>p; if(p>0) f[i]=p; else if(p==0) f[i]=i;//判断是否为主件 //只买主件、主件+附件1,主件+附件2,主件+附件1+附件2,不买 if(i==f[i]){ weight[i][0]=m;//本身 value[i][0]=m*v; } else{//附件 if(flag[p]==1){//是第一个附件 weight[p][1]=m; value[p][1]=v*m; flag[p]=2; } else if(flag[p]==2){//是第二个附加 weight[p][2]=m; value[p][2]=v*m; } } } dp[0]=0; for(int i=1;i<=n;i++){ if(weight[i][0]>0){ for(int j=T;j>=weight[i][0];j--){ if(j>=weight[i][0]){ dp[j]=max(dp[j],dp[j-weight[i][0]]+value[i][0]);//只买主件 } if(j>=weight[i][1]+weight[i][0]){ //只买附件一和.. dp[j]=max(dp[j],dp[j-weight[i][1]-weight[i][0]]+value[i][1]+value[i][0]); } if(j>=weight[i][2]+weight[i][0]){ //只买附件二和.. dp[j]=max(dp[j],dp[j-weight[i][2]-weight[i][0]]+value[i][2]+value[i][0]); } if(j>=weight[i][1]+weight[i][2]+weight[i][0]){ //都买 dp[j]=max(dp[j],dp[j-weight[i][1]-weight[i][2]-weight[i][0]]+value[i][1]+value[i][2]+value[i][0]); } } } }
待到oi十一月,我花开后百花杀。