forked from algorithmzuo/algorithmbasic2020
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCode03_StoneMerge.java
More file actions
117 lines (107 loc) · 2.67 KB
/
Copy pathCode03_StoneMerge.java
File metadata and controls
117 lines (107 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package class41;
// 四边形不等式:合并石子问题
public class Code03_StoneMerge {
public static int[] sum(int[] arr) {
int N = arr.length;
int[] s = new int[N + 1];
s[0] = 0;
for (int i = 0; i < N; i++) {
s[i + 1] = s[i] + arr[i];
}
return s;
}
public static int w(int[] s, int l, int r) {
return s[r + 1] - s[l];
}
public static int min1(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
int N = arr.length;
int[] s = sum(arr);
return process1(0, N - 1, s);
}
public static int process1(int L, int R, int[] s) {
if (L == R) {
return 0;
}
int next = Integer.MAX_VALUE;
for (int leftEnd = L; leftEnd < R; leftEnd++) {
next = Math.min(next, process1(L, leftEnd, s) + process1(leftEnd + 1, R, s));
}
return next + w(s, L, R);
}
public static int min2(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
int N = arr.length;
int[] s = sum(arr);
int[][] dp = new int[N][N];
// dp[i][i] = 0
for (int L = N - 2; L >= 0; L--) {
for (int R = L + 1; R < N; R++) {
int next = Integer.MAX_VALUE;
// dp(L..leftEnd) + dp[leftEnd+1...R] + 累加和[L...R]
for (int leftEnd = L; leftEnd < R; leftEnd++) {
next = Math.min(next, dp[L][leftEnd] + dp[leftEnd + 1][R]);
}
dp[L][R] = next + w(s, L, R);
}
}
return dp[0][N - 1];
}
public static int min3(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
int N = arr.length;
int[] s = sum(arr);
int[][] dp = new int[N][N];
int[][] best = new int[N][N];
for (int i = 0; i < N - 1; i++) {
best[i][i + 1] = i;
dp[i][i + 1] = w(s, i, i + 1);
}
for (int L = N - 3; L >= 0; L--) {
for (int R = L + 2; R < N; R++) {
int next = Integer.MAX_VALUE;
int choose = -1;
for (int leftEnd = best[L][R - 1]; leftEnd <= best[L + 1][R]; leftEnd++) {
int cur = dp[L][leftEnd] + dp[leftEnd + 1][R];
if (cur <= next) {
next = cur;
choose = leftEnd;
}
}
best[L][R] = choose;
dp[L][R] = next + w(s, L, R);
}
}
return dp[0][N - 1];
}
public static int[] randomArray(int len, int maxValue) {
int[] arr = new int[len];
for (int i = 0; i < len; i++) {
arr[i] = (int) (Math.random() * maxValue);
}
return arr;
}
public static void main(String[] args) {
int N = 15;
int maxValue = 100;
int testTime = 1000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int len = (int) (Math.random() * N);
int[] arr = randomArray(len, maxValue);
int ans1 = min1(arr);
int ans2 = min2(arr);
int ans3 = min3(arr);
if (ans1 != ans2 || ans1 != ans3) {
System.out.println("Oops!");
}
}
System.out.println("测试结束");
}
}