背包问题(0-1背包、完全背包、多重背包)
背包问题
一个背包总容量为V, 现在有N个物品, 第i个物品容量为weight[i], 价值为value[i], 现在往背包里面装东西, 怎样装才能使背包内物品总价值最大.主要分为3类:
1. 0-1背包, 每个物品只能取0个,或者1个.
2. 完全背包, 每个物品可以取无限次.
3. 多重背包, 每种物品都有个数限制, 第i个物品最多可以为num[i]个.
求解思路
利用动态规划(dynamic programming)求最优值的方法,当前状态的最优值可以转化成上一个状态的最优值,与上一个状态转移到当前状态代价的组合求最值。f[i]表示当前状态的最优值,f[i-1]表示上一个状态的最优值,s(i-1, i)表示从状态i-1转移带状态i的代价。则: f[i] = max{f[j], f[j]+s(i-1, i)}
具体问题分类
背包问题可以根据物品个数的限制,有多种情况0-1背包,完全背包,多重背包。
0-1背包问题
0-1背包表示每个物品只有取和不取的状态,即只能取0个或1个。
用子问题定义状态:即f[i][j]表示前i间物品恰放入一个容器为j的背包可以获得的最大价值。状态转移方程为:
f[i][j] = max{f[i-1][j], f[i-1][j-weight[i]]+value[i]}
C代码实现如下:
1 for(int i=1;i<=n;i++) // i、n分别表示物品编号、总物品数 2 { 3 for(int j=m;j>=0;j--) // j、m分别表示剩余容量、总容量 4 { 5 if(j>=v[i]) // v[i]表示物品 i 的体积、money etc. 6 f[j]=max(f[j],f[j-v[i]]+w[i]); // w[i] 表示物品 i 的重要度 7 } 8 }
完全背包问题
完全背包表示每个物品可以取无限次,只要加起来总容量不超过V就可以。
同样可以用f[i][j]表示前i间物品恰放入一个容器为j的背包可以获得的最大价值。则其状态转移方程为:
f[i][j] = max{f[i-1][j-k*weight[i]]+k*value[i]} ,其中(0<=k<=j/weight[i])
C代码实现如下:
1 for(int i=1;i<=n;i++) 2 { 3 for(int j=0;j<=m;i++) 4 { 5 if(j>=v[i]) 6 f[j]=max(f[j],f[j-v[i]]+w[i]); 7 } 8 }
多重背包问题
多重背包是每个物品有不同的个数限制,如第i个物品个数为num[i]。
同样可以用f[i][j]表示前i间物品恰放入一个容器为j的背包可以获得的最大价值,且每个物品数量不超多num[i]。则其状态转移方程为:
f[i][j] = max{f[i-1][j-k*weight[i]]+k*value[i]} ,其中(0<=k<=min{j/weight[i], num[i]})
C代码实现如下:

浙公网安备 33010602011771号