揹包問題(要不斷更新)
一.01揹包優化
Q:N物品,T容量,Wi消耗,Vi價值,每件物品取一個,怎樣價值最大?(還記得在清北手推了二維的轉移方程,但如今並不知道倒序的原理)spa
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時的最大價值
注意:倒序jcode
二.徹底揹包blog
Q:N物品,T容量,Wi消耗,Vi價值,每件物品取隨意個,怎樣價值最大?ci
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]); } }
注意:正序jio
三.多重揹包class
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必定要學會回頭再編輯!二進制
四.二維揹包di
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]); } } } }