
目录
W:背包最大总重量
Y:当前最大总重量限制(遍历时会变动:0~W)
N:物品的总数量
w_j:物品 j 的重量(j=0~N)
p_j:物品 j 的价值
A(j, Y):总重量不超过Y的前提下,前 j 个物品的最高价值

单重+单价\总重Y | 0 | 1 | 5 | 9 |
|---|---|---|---|---|
0,0 | ||||
1,2 | ||||
4,3 | ||||
5,4 |
对于j=0,A(0, Y) = 0;
对于Y=0,A(Y,0) = 0。
单重+单价\总重Y | 0 | 1 | 5 | 9 |
|---|---|---|---|---|
0,0 | 0 | 0 | 0 | 0 |
2,2 | 0 | |||
4,3 | 0 | |||
5,4 | 0 |
对于j=1,wj=2,pj=2,Y=1时,有wj > Y,因此放不下,所以沿用前(j-1)个时的价值,而Y不变。

单重+单价\总重Y | 0 | 1 | 5 | 9 |
|---|---|---|---|---|
0,0 | 0 | 0 | 0 | 0 |
2,2 | 0 | 0 | ||
4,3 | 0 | |||
5,4 | 0 |

有可能放入后的总价值,还不如不放入的高。
比如:总重量5,已经放入了(4,5),现在要放进去(2,1),挤出去(2,2),那总重量更新为(4,4),总价值变得更小了。 0560,00002,302,32,204,52,104,4??
对于j=1,wj=2,pj=2,Y=5时,有wj < Y,因此可以放下。
A(j-1,Y):不放入当前物品时的最大价值。
A(j-1,Y-wj):对于前j-1个物品,最大值重量为Y-wj时,看它能存的最大总价值是多少。
pj+A(j-1,Y-wj):即先看去掉当前物品重量后,能存的最大价值,再加上当前物品的价值。
单重+单价\总重Y | 0 | 1 | 5 | 9 |
|---|---|---|---|---|
0,0 | 0 | 0 | 0 | 0 |
2,2 | 0 | 0 | 2,2 | 2,2 |
4,3 | 0 | 0 | 4,3 | 6,5 |
5,4 | 0 | 0 | 5,4 | 9,7 |

前 i 个物品,在最大重量限制为 j 的情况下,最大价值为 dp[i][j]。
两层for循环:
for i in range(1, N+1):
for j in range(1, W+1):
... ...class Solution:
def package(self, N, W, weights, values):
# 创建数组并初始化
dp = [[0 for _ in range(W+1)] for _ in range(N+1)]
# 遍历物品
for i in range(1, N+1):
# 当前物品重量
pi = values[i-1]
# 当前物品价值
wi = weights[i-1]
# 遍历背包
for j in range(1, W+1):
# 放不下的情况
if wi > j:
# 沿用前面的价值
dp[i][j] = dp[i-1][j]
# 放得下的情况
else:
# 取"放"和"不放"两者的较大值
dp[i][j] = max(dp[i-1][j], pi+dp[i-1][j-wi])
for i in dp: print(i)
# 输出结果
print(dp[-1][-1])[0, 0, 0, 0, 0]
[0, 0, 4, 4, 4]
[0, 2, 4, 6, 6]
[0, 2, 4, 6, 6]
6