0-1 背包问题:给定 n 种物品和一个容量为 C 的背包,物品 i 的重量是 wi,其价值为 vi 。

问:应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大?

面对每个物品,我们只有选择拿取或者不拿两种选择,不能选择装入某物品的一部分,也不能装入同一物品多次。

解决办法:声明一个大小为 dp[n][V] 的二维数组, dp[i][j] 表示 在面对第 i 件物品,且背包容量为 j 时所能获得的最大价值 ,那么我们可以很容易分析得出dp[i][j] 的计算方法

(1) j < w[i] 的情况,这时候背包容量不足以放下第 i 件物品,只能选择不拿 dp[ i ][ j ] = dp[ i-1 ][ j ]

(2) j>=w[i] 的情况,这时背包容量可以放下第 i 件物品,我们就要考虑拿这件物品是否能获取更大的价值。

  • 如果拿取,dp[ i ][ j ]=dp[ i-1 ][ j-w[ i ] ] + v[ i ]。 这里的dp[ i-1 ][ j-w[ i ] ]指的就是考虑了i-1件物品,背包容量为j-w[i]时的最大价值,也是相当于为第i件物品腾出了w[i]的空间。
  • 如果不拿,dp[ i ][ j ] = dp[ i-1 ][ j ] , 同(1)

究竟是拿还是不拿,自然是比较这两种情况那种价值最大。

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 计算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 i in range(n):
            for j in range(V,-1,-1):
                if j>=vw[i][0]:
                    dp[j] = max(dp[j],dp[j-vw[i][0]]+vw[i][1])
        return dp[-1]