0/1背包

给定n种物品和一个背包,物品i的重量为wi,价值为vi,背包的总容量为C。
在入背包的物品时对每种物品i只有两种选择,即装入背包和不装入背包(称为0/1背包),如何选择装入背包的物品使得背包中物品总价值最大?

xi = 0时不装入背包,xi = 1时装入背包:

约束条件:装入背包的物品重量之和不超过背包总容量
在这里插入图片描述
目标函数:装入背包的物品价值之和最大
在这里插入图片描述

实例讲解

有四个物品,重量分别为2,3,6,5,价值分别为6,3,5,4,背包的容量为9。
在这里插入图片描述
B(k,c),k代表前k个物品,c代表背包剩下的容量
例如B(2,9):背包剩下的容量是9时还有2个物品

公式推导
假设现在背包里已经有前两个物品,背包容量为0,这时想放第三个物品,发现重量w3太重大于背包容量c,已经放不下,则B(k-1,c)

那么现在假设背包容量足够大,可以放下第j个物品,我们可以有两个选择,放/不放。
放进去:B(k-1,c-cj)+vj(c-cj:背包剩余容量再减去物品重量,vj是物品价值)
不放进去:B(k-1,c)

故公式:
图片说明

DP求解0/1背包

建立一个二维表dp[][],行数为n+1,列数为C+1。
行数和列数都要加1是因为有一行和一列比较特殊,即背包容量为0和不装物品的情况。
所以一般从dp[1][1]开始填入数据
在这里插入图片描述

  1. 步骤一:只装第1个物品
    由于物品1的重量是2,所以背包容量c小于2的都放不进去,dp[1][1]=0;
    从dp[1][2] 开始填入第一个物品的价值v1=6

在这里插入图片描述
此时dp[1][2]的结果是可由公式计算出来的,B(0,0)和B(0,2)查表可知都是0,因为选择的结果最大所以填入6。
在这里插入图片描述
2. 第二步:装其他物品
这个时候直接用公式同上代入数据即可,最后的答案是dp[4][9],即把4个物品装到容量为9的背包,最大价值11.
在这里插入图片描述

输出0/1背包方案

具体看装了哪些物品,需要倒过来观察。
dp[4][9] = max{dp[3,4]+4(选了物品4的情况),dp[3][9](不选物品4的情况)} = dp[3][9],最大的为不选物品4的情况,说明没有选物品4。
dp[3][9] = max{dp[2,3]+5,dp[2][9]}=dp[2][3]+5=11,说明选了物品3,。
dp[2][3] = max{dp[1,0]+3,dp[1][3]}=dp[1][3],说明没选物品2,。
dp[1][3] = max{dp[0,1]+6,dp[0][3]}=dp[0][1]+6=6,说明选了物品1。

也就是说只要判断所填的值dp[i][j]是等于dp[i-1][j-ni]+vi还是dp[i-1][j],就知道有没有选择第i个物品了。

二、0/1背包题目代码(持续更新)

HDOJ 2602-Bone Collector.:0/1背包模板代码(含输出模板以及滚动数组