01 背包问题是一种典型的Dynamic Programming。
问题描述:
给定一组物品,其中每种物品都有自己的重量和价格,在限定的总重量内,如何选择才能使物品的总价格最高?
一个例子:
现有5个商品,质量W(weight)=[2,2,6,5,4];价值V(value)=[3,6,5,4,6],现考虑装入一个总承重capicity=10的背包,求背包能装商品的最大价值。
问题分解:
1. 承重为0或允许装前0件,此时总价值最高为0;
c[i][j] = 0 i=0 or j=0
2. 新允许的第i件装不下,此时总价值=前i-1件对应承重的总价值;
c[i][j] = c[i-1][j] W[i]>j
3. 第i件装得下。
c[i][j] = max(c[i-1][j], c[i-1][j-W[i]]+V[i]) W[i]<=j
其中c[i][j]为i个物品,限定承重为j时的最大价值。
代码实现:
1. 计算匹配矩阵
def bag(capitity, W, V):
n = len(W) # 商品数量
W = [0] + W
V = [0] + V
c = [[0 for j in range(capitity+1)] for i in range(n+1)]
for i in range(1, n+1):
for j in range(1, capitity+1):
if W[i] <= j:
c[i][j] = max(c[i-1][j], c[i-1][j-W[i]] + V[i])
else:
c[i][j] = c[i-1][j]
return c
2. 统计选择商品编号
def show(capicity, W, c):
n = len(W)
print("最大价值为: ", c[-1][-1])
good_selected = [False for i in range(n)]
j = capicity # 背包剩余可容纳质量
for i in range(1, n+1):
if c[i][j] > c[i-1][j]:
good_selected[i-1] = True
j -= W[i-1]
good_selected = [i for i in range(n) if good_selected[i]]
print("选择的物品为: ", good_selected)
测试:
capicity = 10
weight_list = [2, 2, 6, 5, 4]
value_list = [3, 6, 5, 4, 6]
c = bag(capicity, weight_list, value_list)
show(capicity, weight_list, c)
# 最大价值为: 15
# 选择的物品为: [0, 1, 4]