Skip to content

Commit 93f9000

Browse files
authored
feat: add solutions to lc problem: No.2850 (#1607)
No.2850.Minimum Moves to Spread Stones Over Grid
1 parent c0a9580 commit 93f9000

File tree

9 files changed

+523
-78
lines changed

9 files changed

+523
-78
lines changed

solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README.md

Lines changed: 190 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@
5959

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

62+
**方法一:朴素 BFS**
63+
64+
题目实际上是求一个状态图中从初始状态到目标状态的最短路径,因此可以使用 BFS 求解。初始状态为 `grid`,目标状态为 `[[1, 1, 1], [1, 1, 1], [1, 1, 1]]`,在每次操作中,我们可以将一个单元格大于 $1$ 的石头移动到相邻的一个不超过 $1$ 的单元格。如果找到了目标状态,那么就可以返回当前的层数,即为最少移动次数。
65+
66+
**方法二:状态压缩动态规划**
67+
68+
我们可以把所有值为 $0$ 的单元格坐标 $(i, j)$ 放入数组 $left$ 中,如果单元格的值 $v$ 大于 $1$,那么我们把 $v-1$ 个坐标 $(i, j)$ 放入数组 $right$ 中。那么问题就转化为,每个 $right$ 中的坐标 $(i, j)$ 都要移动到 $left$ 中的一个坐标 $(x, y)$,求最少的移动次数。
69+
70+
我们记 $left$ 的长度为 $n$,那么我们可以使用 $n$ 位二进制数来表示 $left$ 中的每个坐标是否被 $right$ 中的坐标填充,其中 $1$ 表示被填充,而 $0$ 表示未被填充。初始时 $f[i] = \infty$,其余 $f[0]=0$。
71+
72+
考虑 $f[i]$,记当前 $i$ 的二进制表示中 $1$ 的个数为 $k$,我们在 $[0..n)$ 的范围内枚举 $j$,如果 $i$ 的第 $j$ 位为 $1$,那么 $f[i]$ 可以由 $f[i \oplus (1 << j)]$ 转移而来,转移的代价为 $cal(left[k-1], right[j])$,其中 $cal$ 表示两个坐标之间的曼哈顿距离。最终答案为 $f[(1 << n) - 1]$。
73+
74+
时间复杂度 $O(n \times 2^n)$,空间复杂度 $O(2^n)$。其中 $n$ 表示 $left$ 的长度,本题中 $n \le 9$。
75+
6276
<!-- tabs:start -->
6377

6478
### **Python3**
@@ -93,6 +107,32 @@ class Solution:
93107
ans += 1
94108
```
95109

110+
```python
111+
class Solution:
112+
def minimumMoves(self, grid: List[List[int]]) -> int:
113+
def cal(a: tuple, b: tuple) -> int:
114+
return abs(a[0] - b[0]) + abs(a[1] - b[1])
115+
116+
left, right = [], []
117+
for i in range(3):
118+
for j in range(3):
119+
if grid[i][j] == 0:
120+
left.append((i, j))
121+
else:
122+
for _ in range(grid[i][j] - 1):
123+
right.append((i, j))
124+
125+
n = len(left)
126+
f = [inf] * (1 << n)
127+
f[0] = 0
128+
for i in range(1, 1 << n):
129+
k = i.bit_count()
130+
for j in range(n):
131+
if i >> j & 1:
132+
f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j]))
133+
return f[-1]
134+
```
135+
96136
### **Java**
97137

98138
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -163,22 +203,170 @@ class Solution {
163203
}
164204
```
165205

206+
```java
207+
class Solution {
208+
public int minimumMoves(int[][] grid) {
209+
List<int[]> left = new ArrayList<>();
210+
List<int[]> right = new ArrayList<>();
211+
for (int i = 0; i < 3; ++i) {
212+
for (int j = 0; j < 3; ++j) {
213+
if (grid[i][j] == 0) {
214+
left.add(new int[] {i, j});
215+
} else {
216+
for (int k = 1; k < grid[i][j]; ++k) {
217+
right.add(new int[] {i, j});
218+
}
219+
}
220+
}
221+
}
222+
int n = left.size();
223+
int[] f = new int[1 << n];
224+
Arrays.fill(f, 1 << 30);
225+
f[0] = 0;
226+
for (int i = 1; i < 1 << n; ++i) {
227+
int k = Integer.bitCount(i);
228+
for (int j = 0; j < n; ++j) {
229+
if ((i >> j & 1) == 1) {
230+
f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j)));
231+
}
232+
}
233+
}
234+
return f[(1 << n) - 1];
235+
}
236+
237+
private int cal(int[] a, int[] b) {
238+
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
239+
}
240+
}
241+
```
242+
166243
### **C++**
167244

168245
```cpp
169-
246+
class Solution {
247+
public:
248+
int minimumMoves(vector<vector<int>>& grid) {
249+
using pii = pair<int, int>;
250+
vector<pii> left, right;
251+
for (int i = 0; i < 3; ++i) {
252+
for (int j = 0; j < 3; ++j) {
253+
if (grid[i][j] == 0) {
254+
left.emplace_back(i, j);
255+
} else {
256+
for (int k = 1; k < grid[i][j]; ++k) {
257+
right.emplace_back(i, j);
258+
}
259+
}
260+
}
261+
}
262+
auto cal = [](pii a, pii b) {
263+
return abs(a.first - b.first) + abs(a.second - b.second);
264+
};
265+
int n = left.size();
266+
int f[1 << n];
267+
memset(f, 0x3f, sizeof(f));
268+
f[0] = 0;
269+
for (int i = 1; i < 1 << n; ++i) {
270+
int k = __builtin_popcount(i);
271+
for (int j = 0; j < n; ++j) {
272+
if (i >> j & 1) {
273+
f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j]));
274+
}
275+
}
276+
}
277+
return f[(1 << n) - 1];
278+
}
279+
};
170280
```
171281
172282
### **Go**
173283
174284
```go
285+
func minimumMoves(grid [][]int) int {
286+
left := [][2]int{}
287+
right := [][2]int{}
288+
for i := 0; i < 3; i++ {
289+
for j := 0; j < 3; j++ {
290+
if grid[i][j] == 0 {
291+
left = append(left, [2]int{i, j})
292+
} else {
293+
for k := 1; k < grid[i][j]; k++ {
294+
right = append(right, [2]int{i, j})
295+
}
296+
}
297+
}
298+
}
299+
cal := func(a, b [2]int) int {
300+
return abs(a[0]-b[0]) + abs(a[1]-b[1])
301+
}
302+
n := len(left)
303+
f := make([]int, 1<<n)
304+
f[0] = 0
305+
for i := 1; i < 1<<n; i++ {
306+
f[i] = 1 << 30
307+
k := bits.OnesCount(uint(i))
308+
for j := 0; j < n; j++ {
309+
if i>>j&1 == 1 {
310+
f[i] = min(f[i], f[i^(1<<j)]+cal(left[k-1], right[j]))
311+
}
312+
}
313+
}
314+
return f[(1<<n)-1]
315+
}
175316
317+
func min(a, b int) int {
318+
if a < b {
319+
return a
320+
}
321+
return b
322+
}
323+
324+
func abs(x int) int {
325+
if x < 0 {
326+
return -x
327+
}
328+
return x
329+
}
176330
```
177331

178332
### **TypeScript**
179333

180334
```ts
181-
335+
function minimumMoves(grid: number[][]): number {
336+
const left: number[][] = [];
337+
const right: number[][] = [];
338+
for (let i = 0; i < 3; ++i) {
339+
for (let j = 0; j < 3; ++j) {
340+
if (grid[i][j] === 0) {
341+
left.push([i, j]);
342+
} else {
343+
for (let k = 1; k < grid[i][j]; ++k) {
344+
right.push([i, j]);
345+
}
346+
}
347+
}
348+
}
349+
const cal = (a: number[], b: number[]) => {
350+
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
351+
};
352+
const n = left.length;
353+
const f: number[] = Array(1 << n).fill(1 << 30);
354+
f[0] = 0;
355+
for (let i = 0; i < 1 << n; ++i) {
356+
let k = 0;
357+
for (let j = 0; j < n; ++j) {
358+
if ((i >> j) & 1) {
359+
++k;
360+
}
361+
}
362+
for (let j = 0; j < n; ++j) {
363+
if ((i >> j) & 1) {
364+
f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j]));
365+
}
366+
}
367+
}
368+
return f[(1 << n) - 1];
369+
}
182370
```
183371

184372
### **...**

0 commit comments

Comments
 (0)