-
Notifications
You must be signed in to change notification settings - Fork 23
/
Stone Game.java
executable file
·86 lines (69 loc) · 2.42 KB
/
Stone Game.java
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
M
tags: DP
这个DP有点诡异. 需要斟酌。
NOT DONE YET
```
/*
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:
At each step of the game,the player can merge two adjacent piles to a new pile.
The score is the number of stones in the new pile.
You are to determine the minimum of the total score.
Example
[3, 4, 3] return 17
[1, 1, 1, 1] return 8
[4, 4, 5, 9] return 43
Tags Expand
Dynamic Programming
*/
/*
Thoughts:
Based on given outline.
sum[i][j] = stone sum between i and j
f[i][j]: min cost/score if we merge ith pile into jth pile. It can be f[0][1], f[0][2].. or our final result f[0][n-1]
break it by k and check both side f[start][k] and f[start][k+1];
Tricky: add sum[start][end] at the end.
*/
public class Solution {
/**
* @param A an integer array
* @return an integer
*/
public int stoneGame(int[] A) {
// Algorithm: Dynamic Programming
// state: f[start][end] denote the minimum score that we can get if we merge stones from start-th pile to end-th pile into one pile.
// function: f[start][end] = min{f[start][k] + f[k + 1][end] + sum[start][end]}
if (A == null || A.length == 0) {
return 0;
}
int n = A.length;
// initialize f[i][i]
int[][] f = new int[n][n];
for (int i = 0; i < n; i++) {
f[i][i] = 0;
}
// preparation for sum[i][j]
int[][] sum = new int[n][n];
sum[0][0] = A[0];
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];
}
}
// dp
// delta is the distance between the start and end
for (int delta = 1; delta < n; delta++) {
for (int start = 0; start < n - delta; start++) {
int end = start + delta;
//initialize f[start][end]
f[start][end] = Integer.MAX_VALUE;
for (int k = start; k < end; k++) {
f[start][end] = Math.min(f[start][end], f[start][k] + f[k + 1][end] + sum[start][end]);
}
}
}
return f[0][n - 1];
}
}
```