【问题描述】
给定 n 种物品和一个背包。物品i的重量是wi,其价值为 vi,背包的容量为c。
问:将哪些物品装入背包可使 这些物品的重量总和不超过背包容量,且价值总和最大?
【输入形式】在屏幕上输入背包容量、物品数量、每件物品价值和重量。 【输出形式】最优解时所选物品的价值总和及其编号。 【样例输入】
10
5
6 3 5 4 6
2 2 6 5 4
【样例输出】 15 1 2 5
【样例说明】 输入:背包容量10、物品数量5、每件物品价值6, 3, 5, 4, 6和重量2, 2, 6, 5, 4。 输出:最优解时选择物品的价值总和为15,编号为1,2,5。
【0-1背包问题特点】
①在选择装入背包的物品时,对每种物品
i
只有两种选择,即装入背包或不装入背包;
②不能将物品
i
装入背包多次,也不能只装入部分的物品i
。
【形式化描述】
给定c>0, wi>0, vi>0, 1<=i<=n, 要求找出一个n元0-1向量(x1,x2,......xn)( x ∈ {0,1}),使得满足下列条件:
![](https://i-blog.csdnimg.cn/blog_migrate/95795b5e247ef36c14f01efb6863de7b.png)
【递归关系】
设所给0-1背包问题的子问题的最优值为m[i, j],即m[i, j] 是背包容量为 j,可选 择物品为i, i+1, … , n时0-1背包问题的最优值;m[1, c]给出所要求的0-1背包问题的最优值。
由
0-1
背包问题的最优子结构性质,可以建立计算m[i, j]的递归式如下:
![](https://i-blog.csdnimg.cn/blog_migrate/49d2ce6ce9f99c26b9bcf2d1179c2c91.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d6dd6d972c0c02c46f8b9415d5ce5bba.png)
【核心代码】
def bag(n, c, w, v):
# 初始化表格以存储子问题的最大值
value = [[0 for _ in range(c + 1)] for _ in range(n + 1)]
# 填充表格
for i in range(1, n + 1):
for j in range(1, c + 1):
# 如果当前物品的重量小于等于背包容量,选择装入或不装入背包的最大值
if w[i - 1] <= j:
value[i][j] = max(value[i - 1][j], v[i - 1] + value[i - 1][j - w[i - 1]])
else:
# 如果当前物品的重量大于背包容量,不装入背包
value[i][j] = value[i - 1][j]
return value #最大价值矩阵
【完整代码】