Skip to content

Commit 1627579

Browse files
committed
feat: add solutions for lc No.1595
1 parent 0f23b2f commit 1627579

5 files changed

Lines changed: 213 additions & 14 deletions

File tree

solution/1500-1599/1595.Minimum Cost to Connect Two Groups of Points/README.md

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ $$
103103

104104
时间复杂度 $O(m \times n \times 2^n)$,空间复杂度 $O(m \times 2^n)$。其中 $m$ 和 $n$ 分别是第一组和第二组中的点数。
105105

106-
我们注意到 $f[i][j]$ 的转移只与 $f[i - 1][\cdot]$ 以及 $f[i][\cdot]$ 有关,因此我们可以使用滚动数组优化空间复杂度,将空间复杂度优化到 $O(2^n)$。
107-
108106
<!-- tabs:start -->
109107

110108
#### Python3
@@ -218,9 +216,7 @@ function connectTwoGroups(cost: number[][]): number {
218216
const m = cost.length;
219217
const n = cost[0].length;
220218
const inf = 1 << 30;
221-
const f: number[][] = Array(m + 1)
222-
.fill(0)
223-
.map(() => Array(1 << n).fill(inf));
219+
const f = Array.from({ length: m + 1 }, () => Array(1 << n).fill(inf));
224220
f[0][0] = 0;
225221
for (let i = 1; i <= m; ++i) {
226222
for (let j = 0; j < 1 << n; ++j) {
@@ -238,13 +234,45 @@ function connectTwoGroups(cost: number[][]): number {
238234
}
239235
```
240236

237+
#### Rust
238+
239+
```rust
240+
impl Solution {
241+
pub fn connect_two_groups(cost: Vec<Vec<i32>>) -> i32 {
242+
let m = cost.len();
243+
let n = cost[0].len();
244+
let inf = 1 << 30;
245+
246+
let mut f = vec![vec![inf; 1 << n]; m + 1];
247+
f[0][0] = 0;
248+
249+
for i in 1..=m {
250+
for j in 0..(1 << n) {
251+
for k in 0..n {
252+
if (j >> k) & 1 == 1 {
253+
let c = cost[i - 1][k];
254+
f[i][j] = f[i][j].min(f[i][j ^ (1 << k)] + c);
255+
f[i][j] = f[i][j].min(f[i - 1][j] + c);
256+
f[i][j] = f[i][j].min(f[i - 1][j ^ (1 << k)] + c);
257+
}
258+
}
259+
}
260+
}
261+
262+
f[m][(1 << n) - 1]
263+
}
264+
}
265+
```
266+
241267
<!-- tabs:end -->
242268

243269
<!-- solution:end -->
244270

245271
<!-- solution:start -->
246272

247-
### 方法二
273+
### 方法二:状态压缩 + 动态规划(空间优化)
274+
275+
我们注意到 $f[i][j]$ 的转移只与 $f[i - 1][\cdot]$ 以及 $f[i][\cdot]$ 有关,因此我们可以使用滚动数组优化空间复杂度,将空间复杂度优化到 $O(2^n)$。
248276

249277
<!-- tabs:start -->
250278

@@ -387,6 +415,40 @@ function connectTwoGroups(cost: number[][]): number {
387415
}
388416
```
389417

418+
#### Rust
419+
420+
```rust
421+
impl Solution {
422+
pub fn connect_two_groups(cost: Vec<Vec<i32>>) -> i32 {
423+
let m = cost.len();
424+
let n = cost[0].len();
425+
let inf = 1 << 30;
426+
427+
let mut f = vec![inf; 1 << n];
428+
f[0] = 0;
429+
430+
let mut g = f.clone();
431+
432+
for i in 1..=m {
433+
for j in 0..(1 << n) {
434+
g[j] = inf;
435+
for k in 0..n {
436+
if (j >> k) & 1 == 1 {
437+
let c = cost[i - 1][k];
438+
g[j] = g[j].min(g[j ^ (1 << k)] + c);
439+
g[j] = g[j].min(f[j] + c);
440+
g[j] = g[j].min(f[j ^ (1 << k)] + c);
441+
}
442+
}
443+
}
444+
f.clone_from_slice(&g);
445+
}
446+
447+
f[(1 << n) - 1]
448+
}
449+
}
450+
```
451+
390452
<!-- tabs:end -->
391453

392454
<!-- solution:end -->

solution/1500-1599/1595.Minimum Cost to Connect Two Groups of Points/README_EN.md

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,28 @@ Note that there are multiple points connected to point 2 in the first group and
7878

7979
<!-- solution:start -->
8080

81-
### Solution 1
81+
### Solution 1: Bitmask Dynamic Programming
82+
83+
Let $m$ and $n$ denote the number of points in the first group and the second group, respectively.
84+
85+
Since $1 \leq n \leq m \leq 12$, we can use an integer to represent the state of points in the second group — specifically, a binary integer of length $n$, where bit $k$ being $1$ means the $k$-th point in the second group is connected to some point in the first group, and $0$ means it is not.
86+
87+
Next, we define $f[i][j]$ as the minimum cost when the first $i$ points in the first group are all connected, and the state of points in the second group is $j$. Initially, $f[0][0] = 0$ and all other values are positive infinity. The answer is $f[m][2^n - 1]$.
88+
89+
Consider $f[i][j]$ where $i \geq 1$. We enumerate each point $k$ in the second group. If point $k$ is connected to the $i$-th point in the first group, we discuss the following two cases:
90+
91+
- If point $k$ is only connected to the $i$-th point in the first group, then $f[i][j]$ can be transitioned from $f[i][j \oplus 2^k]$ or $f[i - 1][j \oplus 2^k]$, where $\oplus$ denotes the XOR operation;
92+
- If point $k$ is connected to the $i$-th point in the first group as well as other points, then $f[i][j]$ can be transitioned from $f[i - 1][j]$.
93+
94+
In both cases, we take the minimum transition value:
95+
96+
$$
97+
f[i][j] = \min_{k \in \{0, 1, \cdots, n - 1\}} \{f[i][j \oplus 2^k], f[i - 1][j \oplus 2^k], f[i - 1][j]\} + cost[i - 1][k]
98+
$$
99+
100+
Finally, we return $f[m][2^n - 1]$.
101+
102+
The time complexity is $O(m \times n \times 2^n)$ and the space complexity is $O(m \times 2^n)$, where $m$ and $n$ are the number of points in the first group and the second group, respectively.
82103

83104
<!-- tabs:start -->
84105

@@ -193,9 +214,7 @@ function connectTwoGroups(cost: number[][]): number {
193214
const m = cost.length;
194215
const n = cost[0].length;
195216
const inf = 1 << 30;
196-
const f: number[][] = Array(m + 1)
197-
.fill(0)
198-
.map(() => Array(1 << n).fill(inf));
217+
const f = Array.from({ length: m + 1 }, () => Array(1 << n).fill(inf));
199218
f[0][0] = 0;
200219
for (let i = 1; i <= m; ++i) {
201220
for (let j = 0; j < 1 << n; ++j) {
@@ -213,13 +232,45 @@ function connectTwoGroups(cost: number[][]): number {
213232
}
214233
```
215234

235+
#### Rust
236+
237+
```rust
238+
impl Solution {
239+
pub fn connect_two_groups(cost: Vec<Vec<i32>>) -> i32 {
240+
let m = cost.len();
241+
let n = cost[0].len();
242+
let inf = 1 << 30;
243+
244+
let mut f = vec![vec![inf; 1 << n]; m + 1];
245+
f[0][0] = 0;
246+
247+
for i in 1..=m {
248+
for j in 0..(1 << n) {
249+
for k in 0..n {
250+
if (j >> k) & 1 == 1 {
251+
let c = cost[i - 1][k];
252+
f[i][j] = f[i][j].min(f[i][j ^ (1 << k)] + c);
253+
f[i][j] = f[i][j].min(f[i - 1][j] + c);
254+
f[i][j] = f[i][j].min(f[i - 1][j ^ (1 << k)] + c);
255+
}
256+
}
257+
}
258+
}
259+
260+
f[m][(1 << n) - 1]
261+
}
262+
}
263+
```
264+
216265
<!-- tabs:end -->
217266

218267
<!-- solution:end -->
219268

220269
<!-- solution:start -->
221270

222-
### Solution 2
271+
### Solution 2: Bitmask Dynamic Programming (Space Optimization)
272+
273+
We notice that the transition of $f[i][j]$ only depends on $f[i - 1][\cdot]$ and $f[i][\cdot]$, so we can use a rolling array to optimize the space complexity down to $O(2^n)$.
223274

224275
<!-- tabs:start -->
225276

@@ -362,6 +413,40 @@ function connectTwoGroups(cost: number[][]): number {
362413
}
363414
```
364415

416+
#### Rust
417+
418+
```rust
419+
impl Solution {
420+
pub fn connect_two_groups(cost: Vec<Vec<i32>>) -> i32 {
421+
let m = cost.len();
422+
let n = cost[0].len();
423+
let inf = 1 << 30;
424+
425+
let mut f = vec![inf; 1 << n];
426+
f[0] = 0;
427+
428+
let mut g = f.clone();
429+
430+
for i in 1..=m {
431+
for j in 0..(1 << n) {
432+
g[j] = inf;
433+
for k in 0..n {
434+
if (j >> k) & 1 == 1 {
435+
let c = cost[i - 1][k];
436+
g[j] = g[j].min(g[j ^ (1 << k)] + c);
437+
g[j] = g[j].min(f[j] + c);
438+
g[j] = g[j].min(f[j ^ (1 << k)] + c);
439+
}
440+
}
441+
}
442+
f.clone_from_slice(&g);
443+
}
444+
445+
f[(1 << n) - 1]
446+
}
447+
}
448+
```
449+
365450
<!-- tabs:end -->
366451

367452
<!-- solution:end -->
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
impl Solution {
2+
pub fn connect_two_groups(cost: Vec<Vec<i32>>) -> i32 {
3+
let m = cost.len();
4+
let n = cost[0].len();
5+
let inf = 1 << 30;
6+
7+
let mut f = vec![vec![inf; 1 << n]; m + 1];
8+
f[0][0] = 0;
9+
10+
for i in 1..=m {
11+
for j in 0..(1 << n) {
12+
for k in 0..n {
13+
if (j >> k) & 1 == 1 {
14+
let c = cost[i - 1][k];
15+
f[i][j] = f[i][j].min(f[i][j ^ (1 << k)] + c);
16+
f[i][j] = f[i][j].min(f[i - 1][j] + c);
17+
f[i][j] = f[i][j].min(f[i - 1][j ^ (1 << k)] + c);
18+
}
19+
}
20+
}
21+
}
22+
23+
f[m][(1 << n) - 1]
24+
}
25+
}

solution/1500-1599/1595.Minimum Cost to Connect Two Groups of Points/Solution.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ function connectTwoGroups(cost: number[][]): number {
22
const m = cost.length;
33
const n = cost[0].length;
44
const inf = 1 << 30;
5-
const f: number[][] = Array(m + 1)
6-
.fill(0)
7-
.map(() => Array(1 << n).fill(inf));
5+
const f = Array.from({ length: m + 1 }, () => Array(1 << n).fill(inf));
86
f[0][0] = 0;
97
for (let i = 1; i <= m; ++i) {
108
for (let j = 0; j < 1 << n; ++j) {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
impl Solution {
2+
pub fn connect_two_groups(cost: Vec<Vec<i32>>) -> i32 {
3+
let m = cost.len();
4+
let n = cost[0].len();
5+
let inf = 1 << 30;
6+
7+
let mut f = vec![inf; 1 << n];
8+
f[0] = 0;
9+
10+
let mut g = f.clone();
11+
12+
for i in 1..=m {
13+
for j in 0..(1 << n) {
14+
g[j] = inf;
15+
for k in 0..n {
16+
if (j >> k) & 1 == 1 {
17+
let c = cost[i - 1][k];
18+
g[j] = g[j].min(g[j ^ (1 << k)] + c);
19+
g[j] = g[j].min(f[j] + c);
20+
g[j] = g[j].min(f[j ^ (1 << k)] + c);
21+
}
22+
}
23+
}
24+
f.clone_from_slice(&g);
25+
}
26+
27+
f[(1 << n) - 1]
28+
}
29+
}

0 commit comments

Comments
 (0)