Skip to content

Commit c9226e4

Browse files
committedMar 16, 2023
feat: add solutions to lc problem: No.1000
No.1000.Minimum Cost to Merge Stones
1 parent ef484f4 commit c9226e4

File tree

10 files changed

+424
-8
lines changed

10 files changed

+424
-8
lines changed
 

‎solution/1000-1099/1000.Minimum Cost to Merge Stones/README.md

+153-1
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,174 @@
5858

5959
<!-- 这里可写通用的实现逻辑 -->
6060

61+
**方法一:动态规划(区间 DP)+ 前缀和**
62+
63+
不妨记题目中的 $k$ 为 $K$,而 $n$ 为石头的堆数。
64+
65+
我们定义 $f[i][j][k]$ 表示将区间 $[i, j]$ 中的石头合并成 $k$ 堆的最小成本。初始时 $f[i][i][1] = 0$,其他位置的值均为 $\infty$。
66+
67+
注意到 $k$ 的取值范围为 $[1, K]$,因此我们需要枚举 $k$ 的值。
68+
69+
对于 $f[i][j][k]$,我们可以枚举 $i \leq h \lt j$,将区间 $[i, j]$ 拆分成两个区间 $[i, h]$ 和 $[h + 1, j]$,然后将 $[i, h]$ 中的石头合并成 $1$ 堆,将 $[h + 1, j]$ 中的石头合并成 $k - 1$ 堆,最后将这两堆石头合并成一堆,这样就可以将区间 $[i, j]$ 中的石头合并成 $k$ 堆。因此,我们可以得到状态转移方程:
70+
71+
$$
72+
f[i][j][k] = \min_{i \leq h < j} \{f[i][h][1] + f[h + 1][j][k - 1]\}
73+
$$
74+
75+
我们将区间 $[i, j]$ 的 $K$ 堆石头合并成一堆,因此 $f[i][j][1] = f[i][j][K] + \sum_{t = i}^j stones[t]$,其中 $\sum_{t = i}^j stones[t]$ 表示区间 $[i, j]$ 中石头的总数。
76+
77+
最后答案即为 $f[1][n][1]$,其中 $n$ 为石头的堆数。
78+
79+
时间复杂度 $O(n^3)$,空间复杂度 $O(n^3)$。其中 $n$ 为石头的堆数。
80+
6181
<!-- tabs:start -->
6282

6383
### **Python3**
6484

6585
<!-- 这里可写当前语言的特殊实现逻辑 -->
6686

6787
```python
68-
88+
class Solution:
89+
def mergeStones(self, stones: List[int], K: int) -> int:
90+
n = len(stones)
91+
if (n - 1) % (K - 1):
92+
return -1
93+
s = list(accumulate(stones, initial=0))
94+
f = [[[inf] * (K + 1) for _ in range(n + 1)] for _ in range(n + 1)]
95+
for i in range(1, n + 1):
96+
f[i][i][1] = 0
97+
for l in range(2, n + 1):
98+
for i in range(1, n - l + 2):
99+
j = i + l - 1
100+
for k in range(1, K + 1):
101+
for h in range(i, j):
102+
f[i][j][k] = min(f[i][j][k], f[i][h][1] + f[h + 1][j][k - 1])
103+
f[i][j][1] = f[i][j][K] + s[j] - s[i - 1]
104+
return f[1][n][1]
69105
```
70106

71107
### **Java**
72108

73109
<!-- 这里可写当前语言的特殊实现逻辑 -->
74110

75111
```java
112+
class Solution {
113+
public int mergeStones(int[] stones, int K) {
114+
int n = stones.length;
115+
if ((n - 1) % (K - 1) != 0) {
116+
return -1;
117+
}
118+
int[] s = new int[n + 1];
119+
for (int i = 1; i <= n; ++i) {
120+
s[i] = s[i - 1] + stones[i - 1];
121+
}
122+
int[][][] f = new int[n + 1][n + 1][K + 1];
123+
final int inf = 1 << 20;
124+
for (int[][] g : f) {
125+
for(int[] e : g) {
126+
Arrays.fill(e, inf);
127+
}
128+
}
129+
for (int i = 1; i <= n; ++i) {
130+
f[i][i][1] = 0;
131+
}
132+
for (int l = 2; l <= n; ++l) {
133+
for (int i = 1; i + l - 1 <= n; ++i) {
134+
int j = i + l - 1;
135+
for (int k = 1; k <= K; ++k) {
136+
for (int h = i; h < j; ++h) {
137+
f[i][j][k] = Math.min(f[i][j][k], f[i][h][1] + f[h + 1][j][k - 1]);
138+
}
139+
}
140+
f[i][j][1] = f[i][j][K] + s[j] - s[i - 1];
141+
}
142+
}
143+
return f[1][n][1];
144+
}
145+
}
146+
```
147+
148+
### **C++**
149+
150+
```cpp
151+
class Solution {
152+
public:
153+
int mergeStones(vector<int>& stones, int K) {
154+
int n = stones.size();
155+
if ((n - 1) % (K - 1)) {
156+
return -1;
157+
}
158+
int s[n + 1];
159+
s[0] = 0;
160+
for (int i = 1; i <= n; ++i) {
161+
s[i] = s[i - 1] + stones[i - 1];
162+
}
163+
int f[n + 1][n + 1][K + 1];
164+
memset(f, 0x3f, sizeof(f));
165+
for (int i = 1; i <= n; ++i) {
166+
f[i][i][1] = 0;
167+
}
168+
for (int l = 2; l <= n; ++l) {
169+
for (int i = 1; i + l - 1 <= n; ++i) {
170+
int j = i + l - 1;
171+
for (int k = 1; k <= K; ++k) {
172+
for (int h = i; h < j; ++h) {
173+
f[i][j][k] = min(f[i][j][k], f[i][h][1] + f[h + 1][j][k - 1]);
174+
}
175+
}
176+
f[i][j][1] = f[i][j][K] + s[j] - s[i - 1];
177+
}
178+
}
179+
return f[1][n][1];
180+
}
181+
};
182+
```
76183
184+
### **Go**
185+
186+
```go
187+
func mergeStones(stones []int, K int) int {
188+
n := len(stones)
189+
if (n-1)%(K-1) != 0 {
190+
return -1
191+
}
192+
s := make([]int, n+1)
193+
for i, x := range stones {
194+
s[i+1] = s[i] + x
195+
}
196+
f := make([][][]int, n+1)
197+
for i := range f {
198+
f[i] = make([][]int, n+1)
199+
for j := range f[i] {
200+
f[i][j] = make([]int, K+1)
201+
for k := range f[i][j] {
202+
f[i][j][k] = 1 << 20
203+
}
204+
}
205+
}
206+
for i := 1; i <= n; i++ {
207+
f[i][i][1] = 0
208+
}
209+
for l := 2; l <= n; l++ {
210+
for i := 1; i <= n-l+1; i++ {
211+
j := i + l - 1
212+
for k := 2; k <= K; k++ {
213+
for h := i; h < j; h++ {
214+
f[i][j][k] = min(f[i][j][k], f[i][h][k-1]+f[h+1][j][1])
215+
}
216+
}
217+
f[i][j][1] = f[i][j][K] + s[j] - s[i-1]
218+
}
219+
}
220+
return f[1][n][1]
221+
}
222+
223+
func min(a, b int) int {
224+
if a < b {
225+
return a
226+
}
227+
return b
228+
}
77229
```
78230

79231
### **...**

‎solution/1000-1099/1000.Minimum Cost to Merge Stones/README_EN.md

+133-1
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,145 @@ The total cost was 25, and this is the minimum possible.
5959
### **Python3**
6060

6161
```python
62-
62+
class Solution:
63+
def mergeStones(self, stones: List[int], K: int) -> int:
64+
n = len(stones)
65+
if (n - 1) % (K - 1):
66+
return -1
67+
s = list(accumulate(stones, initial=0))
68+
f = [[[inf] * (K + 1) for _ in range(n + 1)] for _ in range(n + 1)]
69+
for i in range(1, n + 1):
70+
f[i][i][1] = 0
71+
for l in range(2, n + 1):
72+
for i in range(1, n - l + 2):
73+
j = i + l - 1
74+
for k in range(1, K + 1):
75+
for h in range(i, j):
76+
f[i][j][k] = min(f[i][j][k], f[i][h][1] + f[h + 1][j][k - 1])
77+
f[i][j][1] = f[i][j][K] + s[j] - s[i - 1]
78+
return f[1][n][1]
6379
```
6480

6581
### **Java**
6682

6783
```java
84+
class Solution {
85+
public int mergeStones(int[] stones, int K) {
86+
int n = stones.length;
87+
if ((n - 1) % (K - 1) != 0) {
88+
return -1;
89+
}
90+
int[] s = new int[n + 1];
91+
for (int i = 1; i <= n; ++i) {
92+
s[i] = s[i - 1] + stones[i - 1];
93+
}
94+
int[][][] f = new int[n + 1][n + 1][K + 1];
95+
final int inf = 1 << 20;
96+
for (int[][] g : f) {
97+
for(int[] e : g) {
98+
Arrays.fill(e, inf);
99+
}
100+
}
101+
for (int i = 1; i <= n; ++i) {
102+
f[i][i][1] = 0;
103+
}
104+
for (int l = 2; l <= n; ++l) {
105+
for (int i = 1; i + l - 1 <= n; ++i) {
106+
int j = i + l - 1;
107+
for (int k = 1; k <= K; ++k) {
108+
for (int h = i; h < j; ++h) {
109+
f[i][j][k] = Math.min(f[i][j][k], f[i][h][1] + f[h + 1][j][k - 1]);
110+
}
111+
}
112+
f[i][j][1] = f[i][j][K] + s[j] - s[i - 1];
113+
}
114+
}
115+
return f[1][n][1];
116+
}
117+
}
118+
```
119+
120+
### **C++**
121+
122+
```cpp
123+
class Solution {
124+
public:
125+
int mergeStones(vector<int>& stones, int K) {
126+
int n = stones.size();
127+
if ((n - 1) % (K - 1)) {
128+
return -1;
129+
}
130+
int s[n + 1];
131+
s[0] = 0;
132+
for (int i = 1; i <= n; ++i) {
133+
s[i] = s[i - 1] + stones[i - 1];
134+
}
135+
int f[n + 1][n + 1][K + 1];
136+
memset(f, 0x3f, sizeof(f));
137+
for (int i = 1; i <= n; ++i) {
138+
f[i][i][1] = 0;
139+
}
140+
for (int l = 2; l <= n; ++l) {
141+
for (int i = 1; i + l - 1 <= n; ++i) {
142+
int j = i + l - 1;
143+
for (int k = 1; k <= K; ++k) {
144+
for (int h = i; h < j; ++h) {
145+
f[i][j][k] = min(f[i][j][k], f[i][h][1] + f[h + 1][j][k - 1]);
146+
}
147+
}
148+
f[i][j][1] = f[i][j][K] + s[j] - s[i - 1];
149+
}
150+
}
151+
return f[1][n][1];
152+
}
153+
};
154+
```
68155
156+
### **Go**
157+
158+
```go
159+
func mergeStones(stones []int, K int) int {
160+
n := len(stones)
161+
if (n-1)%(K-1) != 0 {
162+
return -1
163+
}
164+
s := make([]int, n+1)
165+
for i, x := range stones {
166+
s[i+1] = s[i] + x
167+
}
168+
f := make([][][]int, n+1)
169+
for i := range f {
170+
f[i] = make([][]int, n+1)
171+
for j := range f[i] {
172+
f[i][j] = make([]int, K+1)
173+
for k := range f[i][j] {
174+
f[i][j][k] = 1 << 20
175+
}
176+
}
177+
}
178+
for i := 1; i <= n; i++ {
179+
f[i][i][1] = 0
180+
}
181+
for l := 2; l <= n; l++ {
182+
for i := 1; i <= n-l+1; i++ {
183+
j := i + l - 1
184+
for k := 2; k <= K; k++ {
185+
for h := i; h < j; h++ {
186+
f[i][j][k] = min(f[i][j][k], f[i][h][k-1]+f[h+1][j][1])
187+
}
188+
}
189+
f[i][j][1] = f[i][j][K] + s[j] - s[i-1]
190+
}
191+
}
192+
return f[1][n][1]
193+
}
194+
195+
func min(a, b int) int {
196+
if a < b {
197+
return a
198+
}
199+
return b
200+
}
69201
```
70202

71203
### **...**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
class Solution {
2+
public:
3+
int mergeStones(vector<int>& stones, int K) {
4+
int n = stones.size();
5+
if ((n - 1) % (K - 1)) {
6+
return -1;
7+
}
8+
int s[n + 1];
9+
s[0] = 0;
10+
for (int i = 1; i <= n; ++i) {
11+
s[i] = s[i - 1] + stones[i - 1];
12+
}
13+
int f[n + 1][n + 1][K + 1];
14+
memset(f, 0x3f, sizeof(f));
15+
for (int i = 1; i <= n; ++i) {
16+
f[i][i][1] = 0;
17+
}
18+
for (int l = 2; l <= n; ++l) {
19+
for (int i = 1; i + l - 1 <= n; ++i) {
20+
int j = i + l - 1;
21+
for (int k = 1; k <= K; ++k) {
22+
for (int h = i; h < j; ++h) {
23+
f[i][j][k] = min(f[i][j][k], f[i][h][1] + f[h + 1][j][k - 1]);
24+
}
25+
}
26+
f[i][j][1] = f[i][j][K] + s[j] - s[i - 1];
27+
}
28+
}
29+
return f[1][n][1];
30+
}
31+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
func mergeStones(stones []int, K int) int {
2+
n := len(stones)
3+
if (n-1)%(K-1) != 0 {
4+
return -1
5+
}
6+
s := make([]int, n+1)
7+
for i, x := range stones {
8+
s[i+1] = s[i] + x
9+
}
10+
f := make([][][]int, n+1)
11+
for i := range f {
12+
f[i] = make([][]int, n+1)
13+
for j := range f[i] {
14+
f[i][j] = make([]int, K+1)
15+
for k := range f[i][j] {
16+
f[i][j][k] = 1 << 20
17+
}
18+
}
19+
}
20+
for i := 1; i <= n; i++ {
21+
f[i][i][1] = 0
22+
}
23+
for l := 2; l <= n; l++ {
24+
for i := 1; i <= n-l+1; i++ {
25+
j := i + l - 1
26+
for k := 2; k <= K; k++ {
27+
for h := i; h < j; h++ {
28+
f[i][j][k] = min(f[i][j][k], f[i][h][k-1]+f[h+1][j][1])
29+
}
30+
}
31+
f[i][j][1] = f[i][j][K] + s[j] - s[i-1]
32+
}
33+
}
34+
return f[1][n][1]
35+
}
36+
37+
func min(a, b int) int {
38+
if a < b {
39+
return a
40+
}
41+
return b
42+
}

0 commit comments

Comments
 (0)