diff --git a/Contents/10.Dynamic-Programming/04.Knapsack-Problem/01.Knapsack-Problem-01.md b/Contents/10.Dynamic-Programming/04.Knapsack-Problem/01.Knapsack-Problem-01.md index 212263c2..ebc8d349 100644 --- a/Contents/10.Dynamic-Programming/04.Knapsack-Problem/01.Knapsack-Problem-01.md +++ b/Contents/10.Dynamic-Programming/04.Knapsack-Problem/01.Knapsack-Problem-01.md @@ -67,6 +67,7 @@ $dp[i][w] = \begin{cases} dp[i - 1][w] & w < weight[i - 1] \cr max \lbrace dp[i ```Python class Solution: + # 思路 1:动态规划 + 二维基本思路 def zeroOnePackMethod1(self, weight: [int], value: [int], W: int): size = len(weight) dp = [[0 for _ in range(W + 1)] for _ in range(size + 1)] @@ -74,7 +75,7 @@ class Solution: # 枚举前 i 种物品 for i in range(1, size + 1): # 枚举背包装载重量 - for w in range(1, W + 1): + for w in range(W + 1): # 第 i - 1 件物品装不下 if w < weight[i - 1]: # dp[i][w] 取「前 i - 1 件物品装入载重为 w 的背包中的最大价值」 @@ -137,6 +138,7 @@ $dp[w] = \begin{cases} dp[w] & w < weight[i - 1] \cr max \lbrace dp[w], dp[w - w ```Python class Solution: + # 思路 2:动态规划 + 滚动数组优化 def zeroOnePackMethod2(self, weight: [int], value: [int], W: int): size = len(weight) dp = [0 for _ in range(W + 1)] @@ -232,14 +234,18 @@ $dp[w] = \begin{cases} dp[w] & w < nums[i - 1] \cr max \lbrace dp[w], \quad dp[w ```Python class Solution: + # 思路 2:动态规划 + 滚动数组优化 def zeroOnePackMethod2(self, weight: [int], value: [int], W: int): size = len(weight) dp = [0 for _ in range(W + 1)] + # 枚举前 i 种物品 for i in range(1, size + 1): + # 逆序枚举背包装载重量(避免状态值错误) for w in range(W, weight[i - 1] - 1, -1): + # dp[w] 取「前 i - 1 件物品装入载重为 w 的背包中的最大价值」与「前 i - 1 件物品装入载重为 w - weight[i - 1] 的背包中,再装入第 i - 1 物品所得的最大价值」两者中的最大值 dp[w] = max(dp[w], dp[w - weight[i - 1]] + value[i - 1]) - + return dp[W] def canPartition(self, nums: List[int]) -> bool: @@ -248,7 +254,7 @@ class Solution: return False target = sum_nums // 2 - return self.zeroOnePackOptimization(nums, nums, target) == target + return self.zeroOnePackMethod2(nums, nums, target) == target ``` ##### 思路 1:复杂度分析 diff --git a/Contents/10.Dynamic-Programming/04.Knapsack-Problem/02.Knapsack-Problem-02.md b/Contents/10.Dynamic-Programming/04.Knapsack-Problem/02.Knapsack-Problem-02.md index 72ca542b..5dac7158 100644 --- a/Contents/10.Dynamic-Programming/04.Knapsack-Problem/02.Knapsack-Problem-02.md +++ b/Contents/10.Dynamic-Programming/04.Knapsack-Problem/02.Knapsack-Problem-02.md @@ -51,6 +51,7 @@ $dp[i][w] = max \lbrace dp[i - 1][w - k \times weight[i - 1]] + k \times value[i ```Python class Solution: + # 思路 1:动态规划 + 二维基本思路 def completePackMethod1(self, weight: [int], value: [int], W: int): size = len(weight) dp = [[0 for _ in range(W + 1)] for _ in range(size + 1)] @@ -58,7 +59,7 @@ class Solution: # 枚举前 i 种物品 for i in range(1, size + 1): # 枚举背包装载重量 - for w in range(1, W + 1): + for w in range(W + 1): # 枚举第 i 种物品能取个数 for k in range(w // weight[i - 1] + 1): # dp[i][w] 取所有 dp[i - 1][w - k * weight[i - 1] + k * value[i - 1] 中最大值 @@ -142,7 +143,8 @@ $\quad dp[i][w] = \begin{cases} dp[i - 1][w] & w < weight[i - 1] \cr max \lbrac #### 思路 2:代码 ```Python -class Solution: +class Solution: + # 思路 2:动态规划 + 状态转移方程优化 def completePackMethod2(self, weight: [int], value: [int], W: int): size = len(weight) dp = [[0 for _ in range(W + 1)] for _ in range(size + 1)] @@ -150,7 +152,7 @@ class Solution: # 枚举前 i 种物品 for i in range(1, size + 1): # 枚举背包装载重量 - for w in range(1, W + 1): + for w in range(W + 1): # 第 i - 1 件物品装不下 if w < weight[i - 1]: # dp[i][w] 取「前 i - 1 种物品装入载重为 w 的背包中的最大价值」 @@ -209,6 +211,7 @@ $dp[w] = \begin{cases} dp[w] & w < weight[i - 1] \cr max \lbrace dp[w], \quad d ```Python class Solution: + # 思路 3:动态规划 + 滚动数组优化 def completePackMethod3(self, weight: [int], value: [int], W: int): size = len(weight) dp = [0 for _ in range(W + 1)] diff --git "a/Solutions/0416. \345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\351\233\206.md" "b/Solutions/0416. \345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\351\233\206.md" index 3280738c..efe957f2 100644 --- "a/Solutions/0416. \345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\351\233\206.md" +++ "b/Solutions/0416. \345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\351\233\206.md" @@ -73,14 +73,17 @@ $dp[w] = \begin{cases} dp[w] & w < nums[i - 1] \cr max \lbrace dp[w], dp[w - num ```Python class Solution: - def zeroOnePackOptimization(self, weight: [int], value: [int], W: int): + def zeroOnePack(self, weight: [int], value: [int], W: int): size = len(weight) dp = [0 for _ in range(W + 1)] + # 枚举前 i 种物品 for i in range(1, size + 1): + # 逆序枚举背包装载重量(避免状态值错误) for w in range(W, weight[i - 1] - 1, -1): + # dp[w] 取「前 i - 1 件物品装入载重为 w 的背包中的最大价值」与「前 i - 1 件物品装入载重为 w - weight[i - 1] 的背包中,再装入第 i - 1 物品所得的最大价值」两者中的最大值 dp[w] = max(dp[w], dp[w - weight[i - 1]] + value[i - 1]) - + return dp[W] def canPartition(self, nums: List[int]) -> bool: @@ -89,7 +92,7 @@ class Solution: return False target = sum_nums // 2 - return self.zeroOnePackOptimization(nums, nums, target) == target + return self.zeroOnePack(nums, nums, target) == target ``` ### 思路 1:复杂度分析 diff --git a/Templates/10.Dynamic-Programming/Pack-CompletePack.py b/Templates/10.Dynamic-Programming/Pack-CompletePack.py index 912e222b..2d17b078 100644 --- a/Templates/10.Dynamic-Programming/Pack-CompletePack.py +++ b/Templates/10.Dynamic-Programming/Pack-CompletePack.py @@ -7,7 +7,7 @@ def completePackMethod1(self, weight: [int], value: [int], W: int): # 枚举前 i 种物品 for i in range(1, size + 1): # 枚举背包装载重量 - for w in range(1, W + 1): + for w in range(W + 1): # 枚举第 i 种物品能取个数 for k in range(w // weight[i - 1] + 1): # dp[i][w] 取所有 dp[i - 1][w - k * weight[i - 1] + k * value[i - 1] 中最大值 @@ -23,7 +23,7 @@ def completePackMethod2(self, weight: [int], value: [int], W: int): # 枚举前 i 种物品 for i in range(1, size + 1): # 枚举背包装载重量 - for w in range(1, W + 1): + for w in range(W + 1): # 第 i - 1 件物品装不下 if w < weight[i - 1]: # dp[i][w] 取「前 i - 1 种物品装入载重为 w 的背包中的最大价值」 diff --git a/Templates/10.Dynamic-Programming/Pack-GroupPack.py b/Templates/10.Dynamic-Programming/Pack-GroupPack.py new file mode 100644 index 00000000..176d9279 --- /dev/null +++ b/Templates/10.Dynamic-Programming/Pack-GroupPack.py @@ -0,0 +1,37 @@ +class Solution: + # 思路 1:动态规划 + 二维基本思路 + def groupPackMethod1(self, group_count: [int], weight: [[int]], value: [[int]], W: int): + size = len(group_count) + dp = [[0 for _ in range(W + 1)] for _ in range(size + 1)] + + # 枚举前 i 组物品 + for i in range(1, size + 1): + # 枚举背包装载重量 + for w in range(W + 1): + # 枚举第 i 组物品能取个数 + dp[i][w] = dp[i - 1][w] + for k in range(group_count[i - 1]): + if w >= weight[i - 1][k]: + # dp[i][w] 取所有 dp[i - 1][w - weight[i - 1][k]] + value[i - 1][k] 中最大值 + dp[i][w] = max(dp[i][w], dp[i - 1][w - weight[i - 1][k]] + value[i - 1][k]) + + return dp[size][W] + + # 思路 2:动态规划 + 滚动数组优化 + def groupPackMethod2(self, group_count: [int], weight: [[int]], value: [[int]], W: int): + size = len(group_count) + dp = [0 for _ in range(W + 1)] + + # 枚举前 i 组物品 + for i in range(1, size + 1): + # 逆序枚举背包装载重量 + for w in range(W, -1, -1): + # 枚举第 i 组物品能取个数 + for k in range(group_count[i - 1]): + if w >= weight[i - 1][k]: + # dp[i][w] 取所有 dp[i - 1][w - weight[i - 1][k]] + value[i - 1][k] 中最大值 + dp[w] = max(dp[w], dp[w - weight[i - 1][k]] + value[i - 1][k]) + + return dp[W] + + \ No newline at end of file diff --git a/Templates/10.Dynamic-Programming/Pack-MultiplePack.py b/Templates/10.Dynamic-Programming/Pack-MultiplePack.py index 9f4cb11b..f9ff5553 100644 --- a/Templates/10.Dynamic-Programming/Pack-MultiplePack.py +++ b/Templates/10.Dynamic-Programming/Pack-MultiplePack.py @@ -7,7 +7,7 @@ def multiplePackMethod1(self, weight: [int], value: [int], count: [int], W: int) # 枚举前 i 种物品 for i in range(1, size + 1): # 枚举背包装载重量 - for w in range(1, W + 1): + for w in range(W + 1): # 枚举第 i 种物品能取个数 for k in range(min(count[i - 1], w // weight[i - 1]) + 1): # dp[i][w] 取所有 dp[i - 1][w - k * weight[i - 1] + k * value[i - 1] 中最大值 @@ -35,6 +35,7 @@ def multiplePackMethod2(self, weight: [int], value: [int], count: [int], W: int) def multiplePackMethod3(self, weight: [int], value: [int], count: [int], W: int): weight_new, value_new = [], [] + # 二进制优化 for i in range(len(weight)): cnt = count[i] k = 1 diff --git a/Templates/10.Dynamic-Programming/Pack-ZeroOnePack.py b/Templates/10.Dynamic-Programming/Pack-ZeroOnePack.py index af583d56..95d12ceb 100644 --- a/Templates/10.Dynamic-Programming/Pack-ZeroOnePack.py +++ b/Templates/10.Dynamic-Programming/Pack-ZeroOnePack.py @@ -7,7 +7,7 @@ def zeroOnePackMethod1(self, weight: [int], value: [int], W: int): # 枚举前 i 种物品 for i in range(1, size + 1): # 枚举背包装载重量 - for w in range(1, W + 1): + for w in range(W + 1): # 第 i - 1 件物品装不下 if w < weight[i - 1]: # dp[i][w] 取「前 i - 1 件物品装入载重为 w 的背包中的最大价值」