Skip to content

Commit 0533267

Browse files
authored
fix: update solutions to lc problem: No.2850 (#3292)
1 parent 43c1acb commit 0533267

File tree

5 files changed

+170
-170
lines changed

5 files changed

+170
-170
lines changed

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

+85-85
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,91 @@ class Solution {
180180
}
181181
```
182182

183+
<!-- tabs:end -->
184+
185+
<!-- solution:end -->
186+
187+
<!-- solution:start -->
188+
189+
### 方法二:状态压缩动态规划
190+
191+
我们可以把所有值为 $0$ 的单元格坐标 $(i, j)$ 放入数组 $left$ 中,如果单元格的值 $v$ 大于 $1$,那么我们把 $v-1$ 个坐标 $(i, j)$ 放入数组 $right$ 中。那么问题就转化为,每个 $right$ 中的坐标 $(i, j)$ 都要移动到 $left$ 中的一个坐标 $(x, y)$,求最少的移动次数。
192+
193+
我们记 $left$ 的长度为 $n$,那么我们可以使用 $n$ 位二进制数来表示 $left$ 中的每个坐标是否被 $right$ 中的坐标填充,其中 $1$ 表示被填充,而 $0$ 表示未被填充。初始时 $f[i] = \infty$,其余 $f[0]=0$。
194+
195+
考虑 $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]$。
196+
197+
时间复杂度 $O(n \times 2^n)$,空间复杂度 $O(2^n)$。其中 $n$ 表示 $left$ 的长度,本题中 $n \le 9$。
198+
199+
<!-- tabs:start -->
200+
201+
#### Python3
202+
203+
```python
204+
class Solution:
205+
def minimumMoves(self, grid: List[List[int]]) -> int:
206+
def cal(a: tuple, b: tuple) -> int:
207+
return abs(a[0] - b[0]) + abs(a[1] - b[1])
208+
209+
left, right = [], []
210+
for i in range(3):
211+
for j in range(3):
212+
if grid[i][j] == 0:
213+
left.append((i, j))
214+
else:
215+
for _ in range(grid[i][j] - 1):
216+
right.append((i, j))
217+
218+
n = len(left)
219+
f = [inf] * (1 << n)
220+
f[0] = 0
221+
for i in range(1, 1 << n):
222+
k = i.bit_count()
223+
for j in range(n):
224+
if i >> j & 1:
225+
f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j]))
226+
return f[-1]
227+
```
228+
229+
#### Java
230+
231+
```java
232+
class Solution {
233+
public int minimumMoves(int[][] grid) {
234+
List<int[]> left = new ArrayList<>();
235+
List<int[]> right = new ArrayList<>();
236+
for (int i = 0; i < 3; ++i) {
237+
for (int j = 0; j < 3; ++j) {
238+
if (grid[i][j] == 0) {
239+
left.add(new int[] {i, j});
240+
} else {
241+
for (int k = 1; k < grid[i][j]; ++k) {
242+
right.add(new int[] {i, j});
243+
}
244+
}
245+
}
246+
}
247+
int n = left.size();
248+
int[] f = new int[1 << n];
249+
Arrays.fill(f, 1 << 30);
250+
f[0] = 0;
251+
for (int i = 1; i < 1 << n; ++i) {
252+
int k = Integer.bitCount(i);
253+
for (int j = 0; j < n; ++j) {
254+
if ((i >> j & 1) == 1) {
255+
f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j)));
256+
}
257+
}
258+
}
259+
return f[(1 << n) - 1];
260+
}
261+
262+
private int cal(int[] a, int[] b) {
263+
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
264+
}
265+
}
266+
```
267+
183268
#### C++
184269

185270
```cpp
@@ -306,89 +391,4 @@ function minimumMoves(grid: number[][]): number {
306391

307392
<!-- solution:end -->
308393

309-
<!-- solution:start -->
310-
311-
### 方法二:状态压缩动态规划
312-
313-
我们可以把所有值为 $0$ 的单元格坐标 $(i, j)$ 放入数组 $left$ 中,如果单元格的值 $v$ 大于 $1$,那么我们把 $v-1$ 个坐标 $(i, j)$ 放入数组 $right$ 中。那么问题就转化为,每个 $right$ 中的坐标 $(i, j)$ 都要移动到 $left$ 中的一个坐标 $(x, y)$,求最少的移动次数。
314-
315-
我们记 $left$ 的长度为 $n$,那么我们可以使用 $n$ 位二进制数来表示 $left$ 中的每个坐标是否被 $right$ 中的坐标填充,其中 $1$ 表示被填充,而 $0$ 表示未被填充。初始时 $f[i] = \infty$,其余 $f[0]=0$。
316-
317-
考虑 $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]$。
318-
319-
时间复杂度 $O(n \times 2^n)$,空间复杂度 $O(2^n)$。其中 $n$ 表示 $left$ 的长度,本题中 $n \le 9$。
320-
321-
<!-- tabs:start -->
322-
323-
#### Python3
324-
325-
```python
326-
class Solution:
327-
def minimumMoves(self, grid: List[List[int]]) -> int:
328-
def cal(a: tuple, b: tuple) -> int:
329-
return abs(a[0] - b[0]) + abs(a[1] - b[1])
330-
331-
left, right = [], []
332-
for i in range(3):
333-
for j in range(3):
334-
if grid[i][j] == 0:
335-
left.append((i, j))
336-
else:
337-
for _ in range(grid[i][j] - 1):
338-
right.append((i, j))
339-
340-
n = len(left)
341-
f = [inf] * (1 << n)
342-
f[0] = 0
343-
for i in range(1, 1 << n):
344-
k = i.bit_count()
345-
for j in range(n):
346-
if i >> j & 1:
347-
f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j]))
348-
return f[-1]
349-
```
350-
351-
#### Java
352-
353-
```java
354-
class Solution {
355-
public int minimumMoves(int[][] grid) {
356-
List<int[]> left = new ArrayList<>();
357-
List<int[]> right = new ArrayList<>();
358-
for (int i = 0; i < 3; ++i) {
359-
for (int j = 0; j < 3; ++j) {
360-
if (grid[i][j] == 0) {
361-
left.add(new int[] {i, j});
362-
} else {
363-
for (int k = 1; k < grid[i][j]; ++k) {
364-
right.add(new int[] {i, j});
365-
}
366-
}
367-
}
368-
}
369-
int n = left.size();
370-
int[] f = new int[1 << n];
371-
Arrays.fill(f, 1 << 30);
372-
f[0] = 0;
373-
for (int i = 1; i < 1 << n; ++i) {
374-
int k = Integer.bitCount(i);
375-
for (int j = 0; j < n; ++j) {
376-
if ((i >> j & 1) == 1) {
377-
f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j)));
378-
}
379-
}
380-
}
381-
return f[(1 << n) - 1];
382-
}
383-
384-
private int cal(int[] a, int[] b) {
385-
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
386-
}
387-
}
388-
```
389-
390-
<!-- tabs:end -->
391-
392-
<!-- solution:end -->
393-
394394
<!-- problem:end -->

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

+85-85
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,91 @@ class Solution {
174174
}
175175
```
176176

177+
<!-- tabs:end -->
178+
179+
<!-- solution:end -->
180+
181+
<!-- solution:start -->
182+
183+
### Solution 2: State Compression Dynamic Programming
184+
185+
We can put all the coordinates $(i, j)$ of cells with a value of $0$ into an array $left$. If the value $v$ of a cell is greater than $1$, we put $v-1$ coordinates $(i, j)$ into an array $right$. The problem then becomes that each coordinate $(i, j)$ in $right$ needs to be moved to a coordinate $(x, y)$ in $left$, and we need to find the minimum number of moves.
186+
187+
Let's denote the length of $left$ as $n$. We can use an $n$-bit binary number to represent whether each coordinate in $left$ is filled by a coordinate in $right$, where $1$ represents being filled, and $0$ represents not being filled. Initially, $f[i] = \infty$, and the rest $f[0]=0$.
188+
189+
Consider $f[i]$, let the number of $1$s in the binary representation of $i$ be $k$. We enumerate $j$ in the range $[0..n)$, if the $j$th bit of $i$ is $1$, then $f[i]$ can be transferred from $f[i \oplus (1 << j)]$, and the cost of the transfer is $cal(left[k-1], right[j])$, where $cal$ represents the Manhattan distance between two coordinates. The final answer is $f[(1 << n) - 1]$.
190+
191+
The time complexity is $O(n \times 2^n)$, and the space complexity is $O(2^n)$. Here, $n$ is the length of $left$, and in this problem, $n \le 9$.
192+
193+
<!-- tabs:start -->
194+
195+
#### Python3
196+
197+
```python
198+
class Solution:
199+
def minimumMoves(self, grid: List[List[int]]) -> int:
200+
def cal(a: tuple, b: tuple) -> int:
201+
return abs(a[0] - b[0]) + abs(a[1] - b[1])
202+
203+
left, right = [], []
204+
for i in range(3):
205+
for j in range(3):
206+
if grid[i][j] == 0:
207+
left.append((i, j))
208+
else:
209+
for _ in range(grid[i][j] - 1):
210+
right.append((i, j))
211+
212+
n = len(left)
213+
f = [inf] * (1 << n)
214+
f[0] = 0
215+
for i in range(1, 1 << n):
216+
k = i.bit_count()
217+
for j in range(n):
218+
if i >> j & 1:
219+
f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j]))
220+
return f[-1]
221+
```
222+
223+
#### Java
224+
225+
```java
226+
class Solution {
227+
public int minimumMoves(int[][] grid) {
228+
List<int[]> left = new ArrayList<>();
229+
List<int[]> right = new ArrayList<>();
230+
for (int i = 0; i < 3; ++i) {
231+
for (int j = 0; j < 3; ++j) {
232+
if (grid[i][j] == 0) {
233+
left.add(new int[] {i, j});
234+
} else {
235+
for (int k = 1; k < grid[i][j]; ++k) {
236+
right.add(new int[] {i, j});
237+
}
238+
}
239+
}
240+
}
241+
int n = left.size();
242+
int[] f = new int[1 << n];
243+
Arrays.fill(f, 1 << 30);
244+
f[0] = 0;
245+
for (int i = 1; i < 1 << n; ++i) {
246+
int k = Integer.bitCount(i);
247+
for (int j = 0; j < n; ++j) {
248+
if ((i >> j & 1) == 1) {
249+
f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j)));
250+
}
251+
}
252+
}
253+
return f[(1 << n) - 1];
254+
}
255+
256+
private int cal(int[] a, int[] b) {
257+
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
258+
}
259+
}
260+
```
261+
177262
#### C++
178263

179264
```cpp
@@ -300,89 +385,4 @@ function minimumMoves(grid: number[][]): number {
300385

301386
<!-- solution:end -->
302387

303-
<!-- solution:start -->
304-
305-
### Solution 2: State Compression Dynamic Programming
306-
307-
We can put all the coordinates $(i, j)$ of cells with a value of $0$ into an array $left$. If the value $v$ of a cell is greater than $1$, we put $v-1$ coordinates $(i, j)$ into an array $right$. The problem then becomes that each coordinate $(i, j)$ in $right$ needs to be moved to a coordinate $(x, y)$ in $left$, and we need to find the minimum number of moves.
308-
309-
Let's denote the length of $left$ as $n$. We can use an $n$-bit binary number to represent whether each coordinate in $left$ is filled by a coordinate in $right$, where $1$ represents being filled, and $0$ represents not being filled. Initially, $f[i] = \infty$, and the rest $f[0]=0$.
310-
311-
Consider $f[i]$, let the number of $1$s in the binary representation of $i$ be $k$. We enumerate $j$ in the range $[0..n)$, if the $j$th bit of $i$ is $1$, then $f[i]$ can be transferred from $f[i \oplus (1 << j)]$, and the cost of the transfer is $cal(left[k-1], right[j])$, where $cal$ represents the Manhattan distance between two coordinates. The final answer is $f[(1 << n) - 1]$.
312-
313-
The time complexity is $O(n \times 2^n)$, and the space complexity is $O(2^n)$. Here, $n$ is the length of $left$, and in this problem, $n \le 9$.
314-
315-
<!-- tabs:start -->
316-
317-
#### Python3
318-
319-
```python
320-
class Solution:
321-
def minimumMoves(self, grid: List[List[int]]) -> int:
322-
def cal(a: tuple, b: tuple) -> int:
323-
return abs(a[0] - b[0]) + abs(a[1] - b[1])
324-
325-
left, right = [], []
326-
for i in range(3):
327-
for j in range(3):
328-
if grid[i][j] == 0:
329-
left.append((i, j))
330-
else:
331-
for _ in range(grid[i][j] - 1):
332-
right.append((i, j))
333-
334-
n = len(left)
335-
f = [inf] * (1 << n)
336-
f[0] = 0
337-
for i in range(1, 1 << n):
338-
k = i.bit_count()
339-
for j in range(n):
340-
if i >> j & 1:
341-
f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j]))
342-
return f[-1]
343-
```
344-
345-
#### Java
346-
347-
```java
348-
class Solution {
349-
public int minimumMoves(int[][] grid) {
350-
List<int[]> left = new ArrayList<>();
351-
List<int[]> right = new ArrayList<>();
352-
for (int i = 0; i < 3; ++i) {
353-
for (int j = 0; j < 3; ++j) {
354-
if (grid[i][j] == 0) {
355-
left.add(new int[] {i, j});
356-
} else {
357-
for (int k = 1; k < grid[i][j]; ++k) {
358-
right.add(new int[] {i, j});
359-
}
360-
}
361-
}
362-
}
363-
int n = left.size();
364-
int[] f = new int[1 << n];
365-
Arrays.fill(f, 1 << 30);
366-
f[0] = 0;
367-
for (int i = 1; i < 1 << n; ++i) {
368-
int k = Integer.bitCount(i);
369-
for (int j = 0; j < n; ++j) {
370-
if ((i >> j & 1) == 1) {
371-
f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j)));
372-
}
373-
}
374-
}
375-
return f[(1 << n) - 1];
376-
}
377-
378-
private int cal(int[] a, int[] b) {
379-
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
380-
}
381-
}
382-
```
383-
384-
<!-- tabs:end -->
385-
386-
<!-- solution:end -->
387-
388388
<!-- problem:end -->

0 commit comments

Comments
 (0)