递归解法

  • 要么选要么不选要么没法选

    1. def backtrack(w: [], v: [], W, i) -> int:
    2. # base case
    3. if i == len(w):
    4. return 0
    5. else:
    6. if w[i] <= W:
    7. # 在root处理问题
    8. return max(
    9. v[i] + backtrack(w, v, W - w[i], i + 1),
    10. backtrack(w, v, W, i + 1))
    11. else:
    12. return backtrack(w, v, W, i + 1)
    13. if __name__ == '__main__':
    14. W = 4
    15. w = [2, 1, 3]
    16. v = [4, 2, 3]
    17. print(backtrack(w, v, W, 0))

动态规划解法

  • dp[i][j] 前 i 种物品,在背包容量为j 时的最大价值
  • 状态转移方程动态规划-01背包问题 - 图1
  1. def the_01_package(w: [], v: [], W: int) -> int:
  2. dp = [[0 for j in range(W + 1)] for i in range(len(w) + 1)]
  3. print(len(dp), len(dp[0]))
  4. for i in range(1, len(w) + 1): # 物品
  5. for j in range(1, W + 1): # 可用重量
  6. if w[i - 1] <= j:
  7. dp[i][j] = max(
  8. v[i - 1] + dp[i - 1][j - w[i - 1]], dp[i - 1][j], dp[i - 1][j])
  9. else:
  10. dp[i][j] = dp[i - 1][j]
  11. for row in dp:
  12. print(row)
  13. if __name__ == '__main__':
  14. W = 4
  15. w = [2, 1, 3]
  16. v = [4, 2, 3]
  17. print(the_01_package(w, v, W))
  1. export {};
  2. namespace pkg01_dfs {
  3. function maxValue(W: number, wt: number[], val: number[]) {
  4. function dfs(i: number, W: number): number {
  5. /* base case */
  6. if (i === wt.length || W <= 0) {
  7. return 0;
  8. }
  9. /* make progress */
  10. // 可选
  11. if (W >= wt[i]) {
  12. return Math.max(val[i] + dfs(i + 1, W - wt[i]), dfs(i + 1, W));
  13. }
  14. // 不能选
  15. return dfs(i + 1, W);
  16. }
  17. return dfs(0, W);
  18. }
  19. // console.log(maxValue(4, [2, 1, 3], [4, 2, 3]));
  20. }
  21. namespace pkg01_dp {
  22. function maxValue(W: number, wt: number[], value: number[]) {
  23. /*
  24. * state: dp[w][i] => 背包容量为w的情况下,使用前i件物品能得到的最大价值
  25. * base case: dp[0][*] = 0 dp[*][0] = 0
  26. * make change:
  27. * dp[w][i] = {
  28. * dp[w][i-1] || dp [w-wi][i-1]
  29. *
  30. */
  31. const dp: number[][] = new Array(W + 1)
  32. .fill(0)
  33. .map(() => new Array(wt.length + 1).fill(0));
  34. /* Base case */
  35. for (let i = 0; i <= wt.length; i++) {
  36. dp[0][i] = 0;
  37. }
  38. for (let i = 0; i <= W; i++) {
  39. dp[i][0] = 0;
  40. }
  41. /* Make progress */
  42. for (let w = 1; w <= W; w++) {
  43. for (let i = 1; i <= wt.length; i++) {
  44. if (w >= wt[i - 1]) {
  45. dp[w][i] = Math.max(
  46. value[i - 1] + dp[w - wt[i - 1]][i - 1],
  47. dp[w][i - 1]
  48. );
  49. } else {
  50. dp[w][i] = dp[w][i - 1];
  51. }
  52. }
  53. }
  54. return dp[W][wt.length];
  55. }
  56. console.log(maxValue(4, [2, 1, 3], [4, 2, 3]));
  57. }

总结

  • 二维动态规划
  • 动态规划与回溯
    • 动态规划: 自顶向下考虑, 自底向上求解
    • 回溯: 自顶向下考虑, 自顶向下求解
    • 可以用回溯法思考状态转移方程