Skip to content

Commit 7446980

Browse files
committed
feat: add solutions to lc problem: No.2152
No.2152.Minimum Number of Lines to Cover Points
1 parent c0ac1e6 commit 7446980

File tree

6 files changed

+500
-1
lines changed

6 files changed

+500
-1
lines changed

solution/2100-2199/2152.Minimum Number of Lines to Cover Points/README.md

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,201 @@
4848

4949
<!-- 这里可写通用的实现逻辑 -->
5050

51+
**方法一:状态压缩 + 记忆化搜索**
52+
53+
我们可以用一个整数 `state` 来表示当前已经添加的直线,其中 `state` 的第 $i$ 位表示第 $i$ 条直线是否已经添加。如果 `state` 的第 $i$ 位为 $1$,则表示第 $i$ 条直线已经添加,否则表示第 $i$ 条直线还未添加。
54+
55+
接下来,我们设计一个函数 $dfs(state)$,表示当前已经添加的直线为 `state` 时,至少需要添加多少条直线才能使得每个点至少在一条直线上。那么答案就是 $dfs(0)$。
56+
57+
函数 $dfs(state)$ 的计算过程如下:
58+
59+
- 如果 `state` 的所有位都为 $1$,则说明所有直线都已经添加,返回 $0$。
60+
- 否则,我们枚举当前还未添加的点 $i$,接下来枚举 $j$,我们将 $i$ 和 $j$ 的点连成一条直线,此时的状态为 $nxt = state | 1 << i | 1 << j$,其中 $1 << i$ 表示将第 $i$ 位设置为 $1$,$1 << j$ 表示将第 $j$ 位设置为 $1$。接下来,我们枚举所有 $k$,如果 $i$、$j$ 和 $k$ 三个点共线,则将 $k$ 的状态设置为 $1$,即 $nxt = nxt | 1 << k$。此时,我们可以将 $i$ 和 $j$ 以及 $k$ 这三个点连成一条直线,此时的状态为 $nxt$,此时至少需要添加 $dfs(nxt)$ 条直线,我们取所有情况的最小值,即为 $dfs(state)$ 的值。
61+
62+
为了避免重复计算,我们可以使用记忆化搜索。
63+
64+
时间复杂度 $O(2^n \times n^3)$,空间复杂度 $O(2^n)$。其中 $n$ 为点的数量。
65+
5166
<!-- tabs:start -->
5267

5368
### **Python3**
5469

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

5772
```python
73+
class Solution:
74+
def minimumLines(self, points: List[List[int]]) -> int:
75+
def check(i, j, k):
76+
x1, y1 = points[i]
77+
x2, y2 = points[j]
78+
x3, y3 = points[k]
79+
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1)
5880

81+
@cache
82+
def dfs(state):
83+
if state == (1 << n) - 1:
84+
return 0
85+
ans = inf
86+
for i in range(n):
87+
if not (state >> i & 1):
88+
for j in range(i + 1, n):
89+
nxt = state | 1 << i | 1 << j
90+
for k in range(j + 1, n):
91+
if not (nxt >> k & 1) and check(i, j, k):
92+
nxt |= 1 << k
93+
ans = min(ans, dfs(nxt) + 1)
94+
if i == n - 1:
95+
ans = min(ans, dfs(state | 1 << i) + 1)
96+
return ans
97+
98+
n = len(points)
99+
return dfs(0)
59100
```
60101

61102
### **Java**
62103

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

65106
```java
107+
class Solution {
108+
private int[] f;
109+
private int[][] points;
110+
private int n;
111+
112+
public int minimumLines(int[][] points) {
113+
n = points.length;
114+
this.points = points;
115+
f = new int[1 << n];
116+
return dfs(0);
117+
}
118+
119+
private int dfs(int state) {
120+
if (state == (1 << n) - 1) {
121+
return 0;
122+
}
123+
if (f[state] != 0) {
124+
return f[state];
125+
}
126+
int ans = 1 << 30;
127+
for (int i = 0; i < n; ++i) {
128+
if (((state >> i) & 1) == 0) {
129+
for (int j = i + 1; j < n; ++j) {
130+
int nxt = state | 1 << i | 1 << j;
131+
for (int k = j + 1; k < n; ++k) {
132+
if (((state >> k) & 1) == 0 && check(i, j, k)) {
133+
nxt |= 1 << k;
134+
}
135+
}
136+
ans = Math.min(ans, dfs(nxt) + 1);
137+
}
138+
if (i == n - 1) {
139+
ans = Math.min(ans, dfs(state | 1 << i) + 1);
140+
}
141+
}
142+
}
143+
return f[state] = ans;
144+
}
145+
146+
private boolean check(int i, int j, int k) {
147+
int x1 = points[i][0], y1 = points[i][1];
148+
int x2 = points[j][0], y2 = points[j][1];
149+
int x3 = points[k][0], y3 = points[k][1];
150+
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1);
151+
}
152+
}
153+
```
154+
155+
### **C++**
156+
157+
```cpp
158+
class Solution {
159+
public:
160+
int minimumLines(vector<vector<int>>& points) {
161+
auto check = [&](int i, int j, int k) {
162+
int x1 = points[i][0], y1 = points[i][1];
163+
int x2 = points[j][0], y2 = points[j][1];
164+
int x3 = points[k][0], y3 = points[k][1];
165+
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1);
166+
};
167+
int n = points.size();
168+
int f[1 << n];
169+
memset(f, 0, sizeof f);
170+
function<int(int)> dfs = [&](int state) -> int {
171+
if (state == (1 << n) - 1) return 0;
172+
if (f[state]) return f[state];
173+
int ans = 1 << 30;
174+
for (int i = 0; i < n; ++i) {
175+
if (!(state >> i & 1)) {
176+
for (int j = i + 1; j < n; ++j) {
177+
int nxt = state | 1 << i | 1 << j;
178+
for (int k = j + 1; k < n; ++k) {
179+
if (!(nxt >> k & 1) && check(i, j, k)) {
180+
nxt |= 1 << k;
181+
}
182+
}
183+
ans = min(ans, dfs(nxt) + 1);
184+
}
185+
if (i == n - 1) {
186+
ans = min(ans, dfs(state | 1 << i) + 1);
187+
}
188+
}
189+
}
190+
return f[state] = ans;
191+
};
192+
return dfs(0);
193+
}
194+
};
195+
```
196+
197+
### **Go**
198+
199+
```go
200+
func minimumLines(points [][]int) int {
201+
check := func(i, j, k int) bool {
202+
x1, y1 := points[i][0], points[i][1]
203+
x2, y2 := points[j][0], points[j][1]
204+
x3, y3 := points[k][0], points[k][1]
205+
return (x2-x1)*(y3-y1) == (x3-x1)*(y2-y1)
206+
}
207+
n := len(points)
208+
f := make([]int, 1<<n)
209+
var dfs func(int) int
210+
dfs = func(state int) int {
211+
if state == (1<<n)-1 {
212+
return 0
213+
}
214+
if f[state] > 0 {
215+
return f[state]
216+
}
217+
ans := 1 << 30
218+
for i := 0; i < n; i++ {
219+
if (state >> i & 1) == 0 {
220+
for j := i + 1; j < n; j++ {
221+
nxt := state | 1<<i | 1<<j
222+
for k := j + 1; k < n; k++ {
223+
if (nxt>>k&1) == 0 && check(i, j, k) {
224+
nxt |= 1 << k
225+
}
226+
}
227+
ans = min(ans, dfs(nxt)+1)
228+
}
229+
if i == n-1 {
230+
ans = min(ans, dfs(state|1<<i)+1)
231+
}
232+
}
233+
}
234+
f[state] = ans
235+
return ans
236+
}
237+
return dfs(0)
238+
}
66239
240+
func min(a, b int) int {
241+
if a < b {
242+
return a
243+
}
244+
return b
245+
}
67246
```
68247

69248
### **TypeScript**

solution/2100-2199/2152.Minimum Number of Lines to Cover Points/README_EN.md

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,177 @@
4747
### **Python3**
4848

4949
```python
50-
50+
class Solution:
51+
def minimumLines(self, points: List[List[int]]) -> int:
52+
def check(i, j, k):
53+
x1, y1 = points[i]
54+
x2, y2 = points[j]
55+
x3, y3 = points[k]
56+
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1)
57+
58+
@cache
59+
def dfs(state):
60+
if state == (1 << n) - 1:
61+
return 0
62+
ans = inf
63+
for i in range(n):
64+
if not (state >> i & 1):
65+
for j in range(i + 1, n):
66+
nxt = state | 1 << i | 1 << j
67+
for k in range(j + 1, n):
68+
if not (nxt >> k & 1) and check(i, j, k):
69+
nxt |= 1 << k
70+
ans = min(ans, dfs(nxt) + 1)
71+
if i == n - 1:
72+
ans = min(ans, dfs(state | 1 << i) + 1)
73+
return ans
74+
75+
n = len(points)
76+
return dfs(0)
5177
```
5278

5379
### **Java**
5480

5581
```java
82+
class Solution {
83+
private int[] f;
84+
private int[][] points;
85+
private int n;
86+
87+
public int minimumLines(int[][] points) {
88+
n = points.length;
89+
this.points = points;
90+
f = new int[1 << n];
91+
return dfs(0);
92+
}
93+
94+
private int dfs(int state) {
95+
if (state == (1 << n) - 1) {
96+
return 0;
97+
}
98+
if (f[state] != 0) {
99+
return f[state];
100+
}
101+
int ans = 1 << 30;
102+
for (int i = 0; i < n; ++i) {
103+
if (((state >> i) & 1) == 0) {
104+
for (int j = i + 1; j < n; ++j) {
105+
int nxt = state | 1 << i | 1 << j;
106+
for (int k = j + 1; k < n; ++k) {
107+
if (((state >> k) & 1) == 0 && check(i, j, k)) {
108+
nxt |= 1 << k;
109+
}
110+
}
111+
ans = Math.min(ans, dfs(nxt) + 1);
112+
}
113+
if (i == n - 1) {
114+
ans = Math.min(ans, dfs(state | 1 << i) + 1);
115+
}
116+
}
117+
}
118+
return f[state] = ans;
119+
}
120+
121+
private boolean check(int i, int j, int k) {
122+
int x1 = points[i][0], y1 = points[i][1];
123+
int x2 = points[j][0], y2 = points[j][1];
124+
int x3 = points[k][0], y3 = points[k][1];
125+
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1);
126+
}
127+
}
128+
```
129+
130+
### **C++**
131+
132+
```cpp
133+
class Solution {
134+
public:
135+
int minimumLines(vector<vector<int>>& points) {
136+
auto check = [&](int i, int j, int k) {
137+
int x1 = points[i][0], y1 = points[i][1];
138+
int x2 = points[j][0], y2 = points[j][1];
139+
int x3 = points[k][0], y3 = points[k][1];
140+
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1);
141+
};
142+
int n = points.size();
143+
int f[1 << n];
144+
memset(f, 0, sizeof f);
145+
function<int(int)> dfs = [&](int state) -> int {
146+
if (state == (1 << n) - 1) return 0;
147+
if (f[state]) return f[state];
148+
int ans = 1 << 30;
149+
for (int i = 0; i < n; ++i) {
150+
if (!(state >> i & 1)) {
151+
for (int j = i + 1; j < n; ++j) {
152+
int nxt = state | 1 << i | 1 << j;
153+
for (int k = j + 1; k < n; ++k) {
154+
if (!(nxt >> k & 1) && check(i, j, k)) {
155+
nxt |= 1 << k;
156+
}
157+
}
158+
ans = min(ans, dfs(nxt) + 1);
159+
}
160+
if (i == n - 1) {
161+
ans = min(ans, dfs(state | 1 << i) + 1);
162+
}
163+
}
164+
}
165+
return f[state] = ans;
166+
};
167+
return dfs(0);
168+
}
169+
};
170+
```
56171
172+
### **Go**
173+
174+
```go
175+
func minimumLines(points [][]int) int {
176+
check := func(i, j, k int) bool {
177+
x1, y1 := points[i][0], points[i][1]
178+
x2, y2 := points[j][0], points[j][1]
179+
x3, y3 := points[k][0], points[k][1]
180+
return (x2-x1)*(y3-y1) == (x3-x1)*(y2-y1)
181+
}
182+
n := len(points)
183+
f := make([]int, 1<<n)
184+
var dfs func(int) int
185+
dfs = func(state int) int {
186+
if state == (1<<n)-1 {
187+
return 0
188+
}
189+
if f[state] > 0 {
190+
return f[state]
191+
}
192+
ans := 1 << 30
193+
for i := 0; i < n; i++ {
194+
if (state >> i & 1) == 0 {
195+
for j := i + 1; j < n; j++ {
196+
nxt := state | 1<<i | 1<<j
197+
for k := j + 1; k < n; k++ {
198+
if (nxt>>k&1) == 0 && check(i, j, k) {
199+
nxt |= 1 << k
200+
}
201+
}
202+
ans = min(ans, dfs(nxt)+1)
203+
}
204+
if i == n-1 {
205+
ans = min(ans, dfs(state|1<<i)+1)
206+
}
207+
}
208+
}
209+
f[state] = ans
210+
return ans
211+
}
212+
return dfs(0)
213+
}
214+
215+
func min(a, b int) int {
216+
if a < b {
217+
return a
218+
}
219+
return b
220+
}
57221
```
58222

59223
### **TypeScript**

0 commit comments

Comments
 (0)