There is a stone game. At the beginning of the game the player picks n piles of stones in a line.

The goal is to merge the stones in one pile observing the following rules:

  1. At each step of the game,the player can merge two adjacent piles to a new pile.
  2. The score is the number of stones in the new pile.

You are to determine the minimum of the total score.

Example
For [4, 1, 1, 4], in the best solution, the total score is 18:

1
2
3
1. Merge second and third piles => [4, 2, 4], score +2
2. Merge the first two piles => [6, 4],score +6
3. Merge the last two piles => [10], score +10

Other two examples:
[1, 1, 1, 1] return 8
[4, 4, 5, 9] return 43


自顶向下
动态规划四要素:

  1. State: dp[i][j] 表示把第i到第j个石子合并到一起的最小花费
  2. Function: dp[i][j] = min(dp[i][k] + dp[k + 1][j] + sum[i][j]), k 属于 [i, j)
  3. Initialize:
  4. Answer: dp[0][n - 1]
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
public int stoneGame(int[] A) {
if (A == null || A.length == 0)
return 0;
int n = A.length;
int[][] dp = new int[n][n];
boolean[][] visited = new boolean[n][n];
int[][] sum = new int[n][n];
for (int i = 0; i < n; i++) {
sum[i][i] = A[i];
for (int j = i + 1; j < n; j++) {
sum[i][j] = sum[i][j - 1] + A[j];
}
}
return search(0, n - 1, A, dp, visited, sum);
}
public int search(int l, int r, int[] A, int[][] dp, boolean[][] visited, int[][] sum) {
if (l == r) {
return 0;
} else {
if (visited[l][r])
return dp[l][r];
int min = Integer.MAX_VALUE;
for (int i = l; i < r; i++) {
min = Math.min(search(l, i, A, dp, visited, sum) + search(i + 1, r, A, dp, visited, sum) + sum[l][r], min);
}
dp[l][r] = min;
visited[l][r] = true;
return dp[l][r];
}
}