# 记忆化搜索 # 时间复杂度O(n*capacity),空间复杂度O(n*capacity) defzero_one_knapsack(capacity:int, w:List[int], v: List[int])->int: n = len(w) @cache defdfs(i, c): if i < 0: return0 if c < w[i]: return dfs(i-1,c) returnmax(dfs(i-1,c), dfs(i-1,c-w[i]) + v[i]) return dfs(n-1,capacity)
# 递推,1:1翻译 # 时间复杂度O(n*capacity),空间复杂度O(n*capacity) defzero_one_knapsack(capacity:int, w:List[int], v:List[int]) -> int: n=len(w) f = [[0]*(capacity+1) for _ inrange(n+1)] for i,x inenumerate(w): for c inrange(capacity+1): if c < x: f[i+1][c] = f[i][c] else: f[i+1][c] = max(f[i][c], f[i][c-x] + v[i]) return f[n][capacity]
# 递推,滚动数组 # 时间复杂度O(n*capacity),空间复杂度O(capacity) defunbounded_knapsack(capacity:int, w:List[int], v:List[int]) -> int: n=len(w) f = [[0]*(capacity+1) for _ inrange(2)] for i,x inenumerate(w): for c inrange(capacity+1): if c < x: f[(i+1)%2][c] = f[i%2][c] else: f[(i+1)%2][c] = max(f[i%2][c], f[i%2][c-x] + v[i]) return f[n%2][capacity]
# 递推,只用一个数组 # 时间复杂度O(n*capacity),空间复杂度O(capacity) defzero_one_knapsack(capacity:int, w:List[int], v:List[int]) -> int: n=len(w) f = [[0]*(capacity+1) for _ inrange(2)] for x in w: for c inrange(capacity, x-1, -1): # 倒序遍历,因为f[i+1][c]的结果来自f[i][c]和f[i][c-x],前面先算会覆盖掉 f[c] = max(f[c], f[c-x] + v[i]) return f[capacity]
# 记忆化搜索 # 时间复杂度O(n*capacity),空间复杂度O(n*capacity) defunbounded_knapsack(capacity:int, w:List[int], v: List[int]) -> int: n=len(w) @cache defdfs(i, c): if i < 0: return0 if c < w[i]: return dfs(i-1,c) returnmax(dfs(i-1,c), dfs(i,c-w[i]) + v[i]) # 跟0-1背包唯一的区别就是i-1换成i,表示可以递推到自己 return dfs(n-1,capacity)
# 递推,1:1翻译 # 时间复杂度O(n*capacity),空间复杂度O(n*capacity) defunbounded_knapsack(capacity:int, w:List[int], v:List[int]) -> int: n=len(w) f = [[0]*(capacity+1) for _ inrange(n+1)] for i,x inenumerate(w): for c inrange(capacity+1): if c < x: f[i+1][c] = f[i][c] else: f[i+1][c] = max(f[i][c], f[i+1][c-x] + v[i]) # 跟0-1背包的区别:i换成i+1 return f[n][capacity]
# 递推,滚动数组 # 时间复杂度O(n*capacity),空间复杂度O(capacity) defunbounded_knapsack(capacity:int, w:List[int], v:List[int]) -> int: n=len(w) f = [[0]*(capacity+1) for _ inrange(2)] for i,x inenumerate(w): for c inrange(capacity+1): if c < x: f[(i+1)%2][c] = f[i%2][c] else: f[(i+1)%2][c] = max(f[i%2][c], f[(i+1)%2][c-x] + v[i]) # 跟0-1背包的区别:i换成i+1 return f[n%2][capacity]
# 递推,只用一个数组 # 时间复杂度O(n*capacity),空间复杂度O(capacity) defunbounded_knapsack(capacity:int, w:List[int], v:List[int]) -> int: n=len(w) f = [[0]*(capacity+1) for _ inrange(2)] for x in w: for c inrange(x, capacity+1): # 跟0-1背包的区别:正序遍历就行。因为f[i+1][c]的结果来自f[i][c]和f[i+1][c-x],需要先算前面给后面做铺垫 f[c] = max(f[c], f[c-x] + v[i]) return f[capacity]