动态规划问题关键特征

  • 最优子结构

    原问题的最优解涉及多个子问题 在确定最优解使用哪些子问题时,需要考虑多种选择

  • 重叠子问题

    费波纳数列image.png

    ```java package com.algorithm.demo.dongtaiguihua;

/**

  • @Author leijs
  • @date 2022/4/15 */ public class Fibnacci { public static void main(String[] args) {

    1. long start = System.currentTimeMillis();
    2. System.out.println(fibnacci(40));
    3. long end = System.currentTimeMillis();
    4. System.out.println(end - start);
    5. long start1 = System.currentTimeMillis();
    6. System.out.println(fibnacci2(40));
    7. long end1 = System.currentTimeMillis();
    8. System.out.println(end1 - start1);

    }

    public static int fibnacci2(int n) {

    1. int[] res = new int[n + 1];
    2. res[0] = 0;
    3. res[1] = 1;
    4. res[2] = 1;
    5. if (n > 2) {
    6. for (int i = 3; i <= n; i++) {
    7. res[i] = res[i - 1] + res[i - 2];
    8. }
    9. }
    10. return res[n];

    }

    // 递归实现 public static int fibnacci(int n) {

    1. if (n == 1 || n == 2) {
    2. return 1;
    3. }
    4. return fibnacci(n - 1) + fibnacci(n - 2);

    } }

  1. <a name="bUEBf"></a>
  2. ## 钢条切割问题
  3. ![1650033120(1).png](https://cdn.nlark.com/yuque/0/2022/png/999234/1650033132488-722b1bbd-7ac1-407b-9a73-3af68a5b231e.png#clientId=ua10111ab-2091-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=292&id=u3d288f19&margin=%5Bobject%20Object%5D&name=1650033120%281%29.png&originHeight=328&originWidth=788&originalType=binary&ratio=1&rotation=0&showTitle=false&size=72089&status=done&style=none&taskId=uf51c7921-d711-47b6-b3e3-2a75b5924c9&title=&width=700.4444444444445)<br />![1650033269(1).png](https://cdn.nlark.com/yuque/0/2022/png/999234/1650033277135-b9526cd0-a068-45eb-b559-577ba51bb2e7.png#clientId=ua10111ab-2091-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=228&id=u396e2847&margin=%5Bobject%20Object%5D&name=1650033269%281%29.png&originHeight=256&originWidth=728&originalType=binary&ratio=1&rotation=0&showTitle=false&size=67795&status=done&style=none&taskId=ubb8affc5-14f8-4efe-8841-a5c9163e488&title=&width=647.1111111111111)<br />![1650033437(1).png](https://cdn.nlark.com/yuque/0/2022/png/999234/1650033442519-219aed0c-f4ff-417e-a526-8fa561e5588b.png#clientId=ua10111ab-2091-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=291&id=u604f5350&margin=%5Bobject%20Object%5D&name=1650033437%281%29.png&originHeight=327&originWidth=764&originalType=binary&ratio=1&rotation=0&showTitle=false&size=66912&status=done&style=none&taskId=ub331ba8e-cc54-443f-91be-67c3e16690d&title=&width=679.1111111111111)<br />![1650033746(1).png](https://cdn.nlark.com/yuque/0/2022/png/999234/1650033754192-25dbdb11-e1b6-4d44-b10e-f0038a716540.png#clientId=ua10111ab-2091-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=383&id=uc8baa320&margin=%5Bobject%20Object%5D&name=1650033746%281%29.png&originHeight=431&originWidth=837&originalType=binary&ratio=1&rotation=0&showTitle=false&size=103462&status=done&style=none&taskId=u59f0eadb-1af5-4598-8cee-9d66bbd0705&title=&width=744)![image.png](https://cdn.nlark.com/yuque/0/2022/png/999234/1650034045603-44246e80-12d2-465d-be93-afcf18b01107.png#clientId=ua10111ab-2091-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=317&id=ua59228f2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=357&originWidth=842&originalType=binary&ratio=1&rotation=0&showTitle=false&size=136769&status=done&style=none&taskId=u747676f4-8cea-4cba-ac72-1eb0ea4c6a6&title=&width=748.4444444444445)
  4. > 小问题的最优解可以转化为大问题的最优解
  5. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/999234/1650034258544-c51e8845-3670-4c1d-87f2-8e6d74af6522.png#clientId=ua10111ab-2091-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=334&id=u7d0eb193&margin=%5Bobject%20Object%5D&name=image.png&originHeight=376&originWidth=809&originalType=binary&ratio=1&rotation=0&showTitle=false&size=105098&status=done&style=none&taskId=u286ff3ae-6400-4930-8707-cffffb36806&title=&width=719.1111111111111)
  6. ```java
  7. package com.algorithm.demo.dongtaiguihua;
  8. import com.alibaba.fastjson.JSONObject;
  9. import com.google.common.collect.Lists;
  10. import java.util.List;
  11. /**
  12. * @Author leijs
  13. * @date 2022/4/15
  14. */
  15. public class CutRod {
  16. public static int[] price = new int[]{0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
  17. public static void main(String[] args) {
  18. long start = System.nanoTime();
  19. System.out.println(cutRodRecurision(price, 9));
  20. long end = System.nanoTime();
  21. System.out.println(end - start);
  22. long start1 = System.nanoTime();
  23. System.out.println(cutRodRecurision2(price, 9));
  24. long end1 = System.nanoTime();
  25. System.out.println(end1 - start1);
  26. long start2 = System.nanoTime();
  27. System.out.println(cutRodDp(price, 9));
  28. long end2 = System.nanoTime();
  29. System.out.println(end2 - start2);
  30. long start3 = System.nanoTime();
  31. System.out.println(cutRodDpExtend(price, 9)[9]);
  32. long end3 = System.nanoTime();
  33. System.out.println(end3 - start3);
  34. }
  35. public static int cutRodRecurision2(int[] price, int n) {
  36. // 左边不切割,右边切割的场景
  37. if (0 == n) {
  38. // 长度是0
  39. return 0;
  40. }
  41. int res = price[n];
  42. for (int i = 1; i <= n; i++) {
  43. res = Math.max(res, price[i] + cutRodRecurision(price, n - i));
  44. }
  45. return res;
  46. }
  47. public static int cutRodRecurision(int[] price, int n) {
  48. if (0 == n) {
  49. // 长度是0
  50. return 0;
  51. }
  52. int res = price[n];
  53. for (int i = 1; i < n; i++) {
  54. res = Math.max(res, cutRodRecurision(price, i) + cutRodRecurision(price, n - i));
  55. }
  56. return res;
  57. }
  58. public static int cutRodDp(int[] price, int n) {
  59. int[] r = new int[n + 1];
  60. r[0] = 0;
  61. for (int i = 1; i <= n; i++) {
  62. int res = 0;
  63. for (int j = 1; j < i + 1; j++) {
  64. res = Math.max(res, price[j] + r[i - j]);
  65. }
  66. r[i] = res;
  67. }
  68. return r[n];
  69. }
  70. public static int[] cutRodDpExtend(int[] price, int n) {
  71. int[] r = new int[n + 1];
  72. // 左边这一段的值
  73. int[] s = new int[n + 1];
  74. r[0] = 0;
  75. s[0] = 0;
  76. for (int i = 1; i <= n; i++) {
  77. // res价格的最优值
  78. int res_r = 0;
  79. // 价格最大值对应方案左边不切割部分的长度
  80. int res_s = 0;
  81. for (int j = 1; j < i + 1; j++) {
  82. if (price[j] + r[i - j] > res_r) {
  83. res_r = price[j] + r[i - j];
  84. res_s = j;
  85. }
  86. }
  87. r[i] = res_r;
  88. s[i] = res_s;
  89. }
  90. System.out.println("res_s is :" + JSONObject.toJSONString(s));
  91. List<Integer> ans = Lists.newArrayList();
  92. while (n > 0) {
  93. ans.add(s[n]);
  94. n -= s[n];
  95. }
  96. System.out.println("ans is :" + JSONObject.toJSONString(ans));
  97. System.out.println("r is :" + JSONObject.toJSONString(r));
  98. return r;
  99. }
  100. }

最长公共子序列

1650038889(1).png
1650039465(1).png
1650039541(1).png
1650039614(1).png

  1. package com.algorithm.demo.dongtaiguihua;
  2. /**
  3. * @Author leijs
  4. * @date 2022/4/16
  5. */
  6. public class LcsLength {
  7. public static void main(String[] args) {
  8. System.out.println(lcsLength("ABCBDAB".toCharArray(), "BDCABA".toCharArray()));
  9. System.out.println(lcs("ABCBDAB".toCharArray(), "BDCABA".toCharArray()));
  10. }
  11. public static int lcs(char[] a, char[] b) {
  12. int m = a.length;
  13. int n = b.length;
  14. int[][] arr = new int[m + 1][n + 1];
  15. int[][] c = new int[m + 1][n + 1]; // 1 左上方 2 上方 3 左方
  16. for (int i = 1; i < m + 1; i++) {
  17. for (int j = 1; j < n + 1; j++) {
  18. // 这两个位置字符匹配时,来自左上角 +1
  19. if (a[i - 1] == b[j - 1]) {
  20. arr[i][j] = arr[i - 1][j - 1] + 1;
  21. c[i][j] = 1;
  22. } else if (arr[i - 1][j] > arr[i][j - 1]) {
  23. arr[i][j] = arr[i - 1][j];
  24. c[i][j] = 2;
  25. } else {
  26. arr[i][j] = arr[i][j - 1];
  27. c[i][j] = 3;
  28. }
  29. }
  30. }
  31. // trace back
  32. StringBuilder sb = new StringBuilder();
  33. int i = m;
  34. int j = n;
  35. while (i > 0 && j > 0) {
  36. if (c[i][j] == 1) {
  37. sb.append(a[i - 1]);
  38. i -= 1;
  39. j -= 1;
  40. } else if (c[i][j] == 2) {
  41. i -= 1;
  42. } else {
  43. j -= 1;
  44. }
  45. }
  46. System.out.println("res:" + sb);
  47. return arr[m][n];
  48. }
  49. public static int lcsLength(char[] a, char[] b) {
  50. int m = a.length;
  51. int n = b.length;
  52. int[][] arr = new int[m + 1][n + 1];
  53. for (int i = 1; i < m + 1; i++) {
  54. for (int j = 1; j < n + 1; j++) {
  55. // 这两个位置字符匹配时,来自左上角
  56. if (a[i - 1] == b[j - 1]) {
  57. arr[i][j] = arr[i - 1][j - 1] + 1;
  58. } else {
  59. arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
  60. }
  61. }
  62. }
  63. return arr[m][n];
  64. }
  65. }