最近在复习算法知识写下这篇文章帮助自己理解记忆

01 背包问题

01背包问题的目标是在固定的容量限制内,达到最大的物品价值
01对含义:无法分割物品
01背包问题通常有暴力回溯法和动态规划两种方式来解决

Brute Force

回溯法检查所有组合 时间复杂度为指数级
很容易时间就爆表,这里就不看了

动态规划

动态规划的核心在于寻找子问题,在这个题中我们首先去寻找子问题

寻找子问题

假设背包最大重量为5
物品信息如下

重量价值
物品147
物品235
物品356
物品433
物品528

dp表的每一个位置存储的是这么大的背包,最大收益是多少
我们首先考虑,如果只有物品1, 如果装不下,收益就是0
如果我们的背包可以装下,那么最大收益就是7,我们更新第一行

012345
物品1000077
物品2
物品3
物品4
物品5

通过解决子问题获得到全局问题的解

现在考虑物品2,如果装不下,收益就是上一行相同位置的结果

如果能装下:判断上一行相同位置的结果 此物品价值加上上一行去掉此物品重量后的重量最多能装的价值
由此我们获得状态转移方程

dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+values[i])
012345
物品100 (4 - weight of item 2)0077
物品20005max(7, (5 + 0))
物品3
物品4
物品5

不断迭代

012345
物品1000077
物品2000577
物品3000577
物品4000577
物品50088813

最后结果为13

完整Python代码如下

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 计算01背包问题的结果
# @param V int整型 背包的体积
# @param n int整型 物品的个数
# @param vw int整型二维数组 第一维度为n,第二维度为2的二维数组,vw[i][0],vw[i][1]分别描述i+1个物品的vi,wi
# @return int整型
#
class Solution:
    def knapsack(self, V: int, n: int, vw: List[List[int]]) -> int:
        # write code here
        dp = [[0] * (V + 1) for _ in range(n)]
        for i in range(V + 1):
            if i >= vw[0][0]:
                dp[0][i] = vw[0][1]
        for i in range(1, n):
            for j in range(V + 1):
                if j < vw[i][0]:
                    dp[i][j] = dp[i-1][j]
                else:
                    dp[i][j] = max(dp[i-1][j], dp[i-1][j-vw[i][0]]+vw[i][1])
        return dp[n-1][V]

Hydrogen
2.5k 声望73 粉丝

Write code for fun.