递归解法
要么选要么不选要么没法选
def backtrack(w: [], v: [], W, i) -> int:# base caseif i == len(w):return 0else:if w[i] <= W:# 在root处理问题return max(v[i] + backtrack(w, v, W - w[i], i + 1),backtrack(w, v, W, i + 1))else:return backtrack(w, v, W, i + 1)if __name__ == '__main__':W = 4w = [2, 1, 3]v = [4, 2, 3]print(backtrack(w, v, W, 0))
动态规划解法
dp[i][j]前 i 种物品,在背包容量为j 时的最大价值- 状态转移方程
def the_01_package(w: [], v: [], W: int) -> int:dp = [[0 for j in range(W + 1)] for i in range(len(w) + 1)]print(len(dp), len(dp[0]))for i in range(1, len(w) + 1): # 物品for j in range(1, W + 1): # 可用重量if w[i - 1] <= j:dp[i][j] = max(v[i - 1] + dp[i - 1][j - w[i - 1]], dp[i - 1][j], dp[i - 1][j])else:dp[i][j] = dp[i - 1][j]for row in dp:print(row)if __name__ == '__main__':W = 4w = [2, 1, 3]v = [4, 2, 3]print(the_01_package(w, v, W))
export {};namespace pkg01_dfs {function maxValue(W: number, wt: number[], val: number[]) {function dfs(i: number, W: number): number {/* base case */if (i === wt.length || W <= 0) {return 0;}/* make progress */// 可选if (W >= wt[i]) {return Math.max(val[i] + dfs(i + 1, W - wt[i]), dfs(i + 1, W));}// 不能选return dfs(i + 1, W);}return dfs(0, W);}// console.log(maxValue(4, [2, 1, 3], [4, 2, 3]));}namespace pkg01_dp {function maxValue(W: number, wt: number[], value: number[]) {/** state: dp[w][i] => 背包容量为w的情况下,使用前i件物品能得到的最大价值* base case: dp[0][*] = 0 dp[*][0] = 0* make change:* dp[w][i] = {* dp[w][i-1] || dp [w-wi][i-1]**/const dp: number[][] = new Array(W + 1).fill(0).map(() => new Array(wt.length + 1).fill(0));/* Base case */for (let i = 0; i <= wt.length; i++) {dp[0][i] = 0;}for (let i = 0; i <= W; i++) {dp[i][0] = 0;}/* Make progress */for (let w = 1; w <= W; w++) {for (let i = 1; i <= wt.length; i++) {if (w >= wt[i - 1]) {dp[w][i] = Math.max(value[i - 1] + dp[w - wt[i - 1]][i - 1],dp[w][i - 1]);} else {dp[w][i] = dp[w][i - 1];}}}return dp[W][wt.length];}console.log(maxValue(4, [2, 1, 3], [4, 2, 3]));}
总结
- 二维动态规划
- 动态规划与回溯
- 动态规划: 自顶向下考虑, 自底向上求解
- 回溯: 自顶向下考虑, 自顶向下求解
- 可以用回溯法思考状态转移方程
