动态规划问题关键特征
/**
- @Author leijs
@date 2022/4/15 */ public class Fibnacci { public static void main(String[] args) {
long start = System.currentTimeMillis();
System.out.println(fibnacci(40));
long end = System.currentTimeMillis();
System.out.println(end - start);
long start1 = System.currentTimeMillis();
System.out.println(fibnacci2(40));
long end1 = System.currentTimeMillis();
System.out.println(end1 - start1);
}
public static int fibnacci2(int n) {
int[] res = new int[n + 1];
res[0] = 0;
res[1] = 1;
res[2] = 1;
if (n > 2) {
for (int i = 3; i <= n; i++) {
res[i] = res[i - 1] + res[i - 2];
}
}
return res[n];
}
// 递归实现 public static int fibnacci(int n) {
if (n == 1 || n == 2) {
return 1;
}
return fibnacci(n - 1) + fibnacci(n - 2);
} }
<a name="bUEBf"></a>
## 钢条切割问题
<br /><br /><br />
> 小问题的最优解可以转化为大问题的最优解

```java
package com.algorithm.demo.dongtaiguihua;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import java.util.List;
/**
* @Author leijs
* @date 2022/4/15
*/
public class CutRod {
public static int[] price = new int[]{0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
public static void main(String[] args) {
long start = System.nanoTime();
System.out.println(cutRodRecurision(price, 9));
long end = System.nanoTime();
System.out.println(end - start);
long start1 = System.nanoTime();
System.out.println(cutRodRecurision2(price, 9));
long end1 = System.nanoTime();
System.out.println(end1 - start1);
long start2 = System.nanoTime();
System.out.println(cutRodDp(price, 9));
long end2 = System.nanoTime();
System.out.println(end2 - start2);
long start3 = System.nanoTime();
System.out.println(cutRodDpExtend(price, 9)[9]);
long end3 = System.nanoTime();
System.out.println(end3 - start3);
}
public static int cutRodRecurision2(int[] price, int n) {
// 左边不切割,右边切割的场景
if (0 == n) {
// 长度是0
return 0;
}
int res = price[n];
for (int i = 1; i <= n; i++) {
res = Math.max(res, price[i] + cutRodRecurision(price, n - i));
}
return res;
}
public static int cutRodRecurision(int[] price, int n) {
if (0 == n) {
// 长度是0
return 0;
}
int res = price[n];
for (int i = 1; i < n; i++) {
res = Math.max(res, cutRodRecurision(price, i) + cutRodRecurision(price, n - i));
}
return res;
}
public static int cutRodDp(int[] price, int n) {
int[] r = new int[n + 1];
r[0] = 0;
for (int i = 1; i <= n; i++) {
int res = 0;
for (int j = 1; j < i + 1; j++) {
res = Math.max(res, price[j] + r[i - j]);
}
r[i] = res;
}
return r[n];
}
public static int[] cutRodDpExtend(int[] price, int n) {
int[] r = new int[n + 1];
// 左边这一段的值
int[] s = new int[n + 1];
r[0] = 0;
s[0] = 0;
for (int i = 1; i <= n; i++) {
// res价格的最优值
int res_r = 0;
// 价格最大值对应方案左边不切割部分的长度
int res_s = 0;
for (int j = 1; j < i + 1; j++) {
if (price[j] + r[i - j] > res_r) {
res_r = price[j] + r[i - j];
res_s = j;
}
}
r[i] = res_r;
s[i] = res_s;
}
System.out.println("res_s is :" + JSONObject.toJSONString(s));
List<Integer> ans = Lists.newArrayList();
while (n > 0) {
ans.add(s[n]);
n -= s[n];
}
System.out.println("ans is :" + JSONObject.toJSONString(ans));
System.out.println("r is :" + JSONObject.toJSONString(r));
return r;
}
}
最长公共子序列
package com.algorithm.demo.dongtaiguihua;
/**
* @Author leijs
* @date 2022/4/16
*/
public class LcsLength {
public static void main(String[] args) {
System.out.println(lcsLength("ABCBDAB".toCharArray(), "BDCABA".toCharArray()));
System.out.println(lcs("ABCBDAB".toCharArray(), "BDCABA".toCharArray()));
}
public static int lcs(char[] a, char[] b) {
int m = a.length;
int n = b.length;
int[][] arr = new int[m + 1][n + 1];
int[][] c = new int[m + 1][n + 1]; // 1 左上方 2 上方 3 左方
for (int i = 1; i < m + 1; i++) {
for (int j = 1; j < n + 1; j++) {
// 这两个位置字符匹配时,来自左上角 +1
if (a[i - 1] == b[j - 1]) {
arr[i][j] = arr[i - 1][j - 1] + 1;
c[i][j] = 1;
} else if (arr[i - 1][j] > arr[i][j - 1]) {
arr[i][j] = arr[i - 1][j];
c[i][j] = 2;
} else {
arr[i][j] = arr[i][j - 1];
c[i][j] = 3;
}
}
}
// trace back
StringBuilder sb = new StringBuilder();
int i = m;
int j = n;
while (i > 0 && j > 0) {
if (c[i][j] == 1) {
sb.append(a[i - 1]);
i -= 1;
j -= 1;
} else if (c[i][j] == 2) {
i -= 1;
} else {
j -= 1;
}
}
System.out.println("res:" + sb);
return arr[m][n];
}
public static int lcsLength(char[] a, char[] b) {
int m = a.length;
int n = b.length;
int[][] arr = new int[m + 1][n + 1];
for (int i = 1; i < m + 1; i++) {
for (int j = 1; j < n + 1; j++) {
// 这两个位置字符匹配时,来自左上角
if (a[i - 1] == b[j - 1]) {
arr[i][j] = arr[i - 1][j - 1] + 1;
} else {
arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
}
}
}
return arr[m][n];
}
}