You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
5.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package 01.mca_08_dp;
// 本题测试链接 : https://leetcode.com/problems/burst-balloons/
public class Code06_BurstBalloons {
public static int maxScore1(int[] arr) {
int n = arr.length;
int[] help = new int[n + 2];
help[0] = 1;
help[n + 1] = 1;
for (int i = 1; i <= n; i++) {
help[i] = arr[i - 1];
}
// [3,2,1,4,5] -> [1,3,2,1,4,5,1];
// 0 1 2 3 4 1 2 3 4 5
return process1(help, 1, n);
}
// arr[L...R]上打爆气球,返回最大得分!
// 潜台词 : arr[L-1]这个气球一定没爆arr[R+1]这个气球,一定也没爆!
public static int process1(int[] arr, int L, int R) {
if (L == R) {
return arr[L - 1] * arr[L] * arr[R + 1];
}
// 不止一个气球
// 分析可能性
// 1最后打爆L位置的气球
int p1 = process1(arr, L + 1, R) + arr[L - 1] * arr[L] * arr[R + 1];
// 1最后打爆R位置的气球
int p2 = process1(arr, L, R - 1) + arr[L - 1] * arr[R] * arr[R + 1];
int ans = Math.max(p1, p2);
// 尝试中间每一个气球都最后打爆!
for (int mid = L + 1; mid < R; mid++) {
// arr[mid](最后打爆,一定要最后打爆!)
int cur = process1(arr, L, mid - 1) + process1(arr, mid + 1, R) + arr[L - 1] * arr[mid] * arr[R + 1];
ans = Math.max(ans, cur);
}
return ans;
}
public static int maxScore2(int[] arr) {
int n = arr.length;
int[] help = new int[n + 2];
help[0] = 1;
help[n + 1] = 1;
for (int i = 1; i <= n; i++) {
help[i] = arr[i - 1];
}
int[][] dp = new int[n + 1][n + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
dp[i][j] = -1;
}
}
return process2(help, 1, n, dp);
}
public static int process2(int[] arr, int L, int R, int[][] dp) {
if (dp[L][R] != -1) {
return dp[L][R];
}
int ans = 0;
if (L == R) {
ans = arr[L - 1] * arr[L] * arr[R + 1];
} else {
int p1 = process2(arr, L + 1, R, dp) + arr[L - 1] * arr[L] * arr[R + 1];
int p2 = process2(arr, L, R - 1,dp) + arr[L - 1] * arr[R] * arr[R + 1];
ans = Math.max(p1, p2);
for (int mid = L + 1; mid < R; mid++) {
int cur = process2(arr, L, mid - 1,dp) + process2(arr, mid + 1, R,dp) + arr[L - 1] * arr[mid] * arr[R + 1];
ans = Math.max(ans, cur);
}
}
dp[L][R] = ans;
return ans;
}
public static int maxCoins0(int[] arr) {
// [3,2,1,3]
// [1,3,2,1,3,1]
int N = arr.length;
int[] help = new int[N + 2];
for (int i = 0; i < N; i++) {
help[i + 1] = arr[i];
}
help[0] = 1;
help[N + 1] = 1;
return func(help, 1, N);
}
// L-1位置和R+1位置永远不越界并且[L-1] 和 [R+1] 一定没爆呢!
// 返回arr[L...R]打爆所有气球,最大得分是什么
public static int func(int[] arr, int L, int R) {
if (L == R) {
return arr[L - 1] * arr[L] * arr[R + 1];
}
// 尝试每一种情况,最后打爆的气球,是什么位置
// L...R
// L位置的气球最后打爆
int max = func(arr, L + 1, R) + arr[L - 1] * arr[L] * arr[R + 1];
// R位置的气球最后打爆
max = Math.max(max, func(arr, L, R - 1) + arr[L - 1] * arr[R] * arr[R + 1]);
// 尝试所有L...R中间的位置(L,R)
for (int i = L + 1; i < R; i++) {
// i位置的气球最后打爆
int left = func(arr, L, i - 1);
int right = func(arr, i + 1, R);
int last = arr[L - 1] * arr[i] * arr[R + 1];
int cur = left + right + last;
max = Math.max(max, cur);
}
return max;
}
public static int maxCoins1(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
if (arr.length == 1) {
return arr[0];
}
int N = arr.length;
int[] help = new int[N + 2];
help[0] = 1;
help[N + 1] = 1;
for (int i = 0; i < N; i++) {
help[i + 1] = arr[i];
}
return process(help, 1, N);
}
// 打爆arr[L..R]范围上的所有气球,返回最大的分数
// 假设arr[L-1]和arr[R+1]一定没有被打爆
public static int process(int[] arr, int L, int R) {
if (L == R) {// 如果arr[L..R]范围上只有一个气球,直接打爆即可
return arr[L - 1] * arr[L] * arr[R + 1];
}
// 最后打爆arr[L]的方案和最后打爆arr[R]的方案,先比较一下
int max = Math.max(arr[L - 1] * arr[L] * arr[R + 1] + process(arr, L + 1, R),
arr[L - 1] * arr[R] * arr[R + 1] + process(arr, L, R - 1));
// 尝试中间位置的气球最后被打爆的每一种方案
for (int i = L + 1; i < R; i++) {
max = Math.max(max, arr[L - 1] * arr[i] * arr[R + 1] + process(arr, L, i - 1) + process(arr, i + 1, R));
}
return max;
}
public static int maxCoins2(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
if (arr.length == 1) {
return arr[0];
}
int N = arr.length;
int[] help = new int[N + 2];
help[0] = 1;
help[N + 1] = 1;
for (int i = 0; i < N; i++) {
help[i + 1] = arr[i];
}
int[][] dp = new int[N + 2][N + 2];
for (int i = 1; i <= N; i++) {
dp[i][i] = help[i - 1] * help[i] * help[i + 1];
}
for (int L = N; L >= 1; L--) {
for (int R = L + 1; R <= N; R++) {
int ans = help[L - 1] * help[L] * help[R + 1] + dp[L + 1][R];
ans = Math.max(ans, help[L - 1] * help[R] * help[R + 1] + dp[L][R - 1]);
for (int i = L + 1; i < R; i++) {
ans = Math.max(ans, help[L - 1] * help[i] * help[R + 1] + dp[L][i - 1] + dp[i + 1][R]);
}
dp[L][R] = ans;
}
}
return dp[1][N];
}
}