max ∑ i = 1 n v i x i { ∑ i = 1 n w i x i ≤ c x i ∈ { 0 , 1 } ( 1 ≤ i ≤ n ) \max \displaystyle\sum\limits_{i = 1}^{n}{v_{i} x_{i}} \kern{2em} \begin{cases} \displaystyle\sum\limits_{i = 1}^{n}{w_{i} x_{i} \leq c} \\ x_{i} \in \set{0 , 1} (1 \leq i \leq n) \end{cases} maxi=1∑nvixi⎩ ⎨ ⎧i=1∑nwixi≤cxi∈{0,1}(1≤i≤n)
max ∑ i = 2 n v i x i { ∑ i = 2 n w i x i ≤ c − w 1 y 1 x i ∈ { 0 , 1 } ( 2 ≤ i ≤ n ) \max \displaystyle\sum\limits_{i = 2}^{n}{v_{i} x_{i}} \kern{2em} \begin{cases} \displaystyle\sum\limits_{i = 2}^{n}{w_{i} x_{i}} \leq c - w_{1} y_{1} \\ x_{i} \in \set{0 , 1} (2 \leq i \leq n) \end{cases} maxi=2∑nvixi⎩ ⎨ ⎧i=2∑nwixi≤c−w1y1xi∈{0,1}(2≤i≤n)
m ( i , j ) = { max { m ( i + 1 , j ) , m ( i + 1 , j − w i ) + v i } , j ≥ w i m ( i + 1 , j ) , 0 ≤ j < w i m(i , j) = \begin{cases} \max\set{m(i + 1 , j) , m(i + 1 , j - w_{i}) + v_{i}} , & j \geq w_{i} \\ m(i + 1 , j) , & 0 \leq j < w_{i} \end{cases} m(i,j)={max{m(i+1,j),m(i+1,j−wi)+vi},m(i+1,j),j≥wi0≤j<wi
m ( n , j ) = { v n , j ≥ w n 0 , 0 ≤ j < w n m(n , j) = \begin{cases} v_{n} , & j \geq w_{n} \\ 0 , & 0 \leq j < w_{n} \end{cases} m(n,j)={vn,0,j≥wn0≤j<wn
Python
实现def knapsack(weights, values, capacity):
n = len(weights)
# 创建一个二维数组用于保存子问题的解
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
# 填充二维数组
for i in range(1, n + 1):
for j in range(1, capacity + 1):
# 当前物品的重量大于背包容量, 无法放入背包
if weights[i - 1] > j:
dp[i][j] = dp[i - 1][j]
else:
# 考虑将当前物品放入背包和不放入背包两种情况, 选择价值最大的方案
dp[i][j] = max(dp[i - 1][j], values[i - 1] + dp[i - 1][j - weights[i - 1]])
# 构造最优解
selected_items = []
i, j = n, capacity
while i > 0 and j > 0:
# 当前物品被选中
if dp[i][j] > dp[i - 1][j]:
selected_items.append(i - 1)
j -= weights[i - 1]
i -= 1
selected_items.reverse()
return dp[n][capacity], selected_items
weights = [2, 3, 4, 5]
values = [3, 4, 5, 6]
capacity = 8
max_value, selected_items = knapsack(weights, values, capacity)
print('最大价值为:', max_value)
print('选中的物品索引为:', selected_items)