1. 0—1背包问题
问题描述:
假设我们有 n 件物品
表示第 𝑖 件物品的价值;
表示第 𝑖 件物品的重量;
假设背包的容量为 𝑊;
Goal: 如何最大化背包中物品的总价值?
动态规划求解步骤
Step 1: 分析最优解的性质,刻画其结构特征
Step 2: 递归地定义最优解
最优解为:物品i包含在最优解(物品i+排除物品i其余物品能取的最大价值)/物品i不包含在最优解中(排除物品i其余物品能取的最大价值)
Step 3: 自底向上计算子问题的最优解
通过二维数组V[0...N,0...M]来自底部向上逐渐计算最优解,并通过二维数组keep[0...N,0...M]记录最优解包含的物体
Step 4: 构造问题的最优解
伪代码解析
#输入 v:物体价值的数组 w:物体重量的数组 n:物体的个数 W:背包的容量
#输出 最大背包容量下能取得的最大价值
Input: v and w are values and weights of n items, W is the allowed maximum weight of items.
Output: Maximum value of any subset of items {1, 2, …, n} of weight at most W.
步骤1:构建两个二维数组V ,keep
Let 𝑉[0. . 𝑛, 0. . 𝑊] and 𝑘𝑒𝑒𝑝[0. . n, 0. . W] be two new 2-dimension arrays;
步骤2:初始化二维数组V,将第一行W个元素置为0,即背包中没有物品时最大价值为0
for 𝑤1 = 0 to 𝑊 do
𝑉[ 0, 𝑤1] = 0;
步骤3:两层循环来遍历n个物体,i、w1执行的动作为遍历物体i时,背包的容量为W1时能取到的最大价值
for 𝑖 = 1 to 𝑛 do
for 𝑤1 = 0 to 𝑊 do
if (𝑤[𝑖] ≤ 𝑤1) and (𝑣[ 𝑖] + 𝑉[𝑖 − 1, 𝑤1 − 𝑤[𝑖]]> 𝑉[𝑖 − 1, 𝑤1]) then
𝑉 [𝑖, 𝑤1] = 𝑣[ 𝑖] + 𝑉[𝑖 − 1, 𝑤1 − 𝑤[𝑖]];
keep [𝑖, 𝑤1 ]= 1;
else
𝑉[𝑖, 𝑤1]= 𝑉 [𝑖 − 1, 𝑤1 ];
keep [𝑖, 𝑤1]= 0;
end
end
end
步骤4:寻找最优解,单层循环从【n,k】开始查找keep数组中值为1的即为最优解的一个物品
𝐾 = 𝑊;
for 𝑖 = 𝑛 downto 1 do
if 𝑘𝑒𝑒𝑝 [𝑖,𝐾]== 1 then
output i;
𝐾 = 𝐾 − 𝑤 [𝑖];
end
end
return 𝑉[𝑛, 𝑊]