Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 93f9000

Browse files
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
File renamed without changes.

‎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)

AltStyle によって変換されたページ (->オリジナル) /