comments | difficulty | edit_url | tags | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
true |
中等 |
|
给定一个 points
数组,points[i] = [xi, yi]
表示直角坐标系 X-Y 的一个点。
现在考虑向 X-Y 坐标系中添加 直线,使得每个点 至少 在一条直线上。
返回能够穿过所有点的所需 最少直线 数量。
示例 1:
输入: points = [[0,1],[2,3],[4,5],[4,3]] 输出: 2 解释: 所需最少直线数量为 2 ,一种可能的答案是添加: - 一条穿过点 (0, 1) 和 点(4, 5) 的直线 - 另一条穿过点 (2, 3) 和点 (4, 3) 的直线
示例 2:
输入: points = [[0,2],[-2,-2],[1,4]] 输出: 1 解释: 所需最少直线数量为 1 ,唯一的答案是: - 一条穿过点 (-2, -2) 和点 (1, 4) 的直线
提示:
1 <= points.length <= 10
points[i].length == 2
-100 <= xi, yi <= 100
points
中元素都是唯一的
我们可以用一个整数 state
来表示当前已经添加的直线,其中 state
的第 state
的第
接下来,我们设计一个函数 state
时,至少需要添加多少条直线才能使得每个点至少在一条直线上。那么答案就是
函数
- 如果
state
的所有位都为$1$ ,则说明所有直线都已经添加,返回$0$ 。 - 否则,我们枚举当前还未添加的点
$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)$ 的值。
为了避免重复计算,我们可以使用记忆化搜索。
时间复杂度
class Solution:
def minimumLines(self, points: List[List[int]]) -> int:
def check(i, j, k):
x1, y1 = points[i]
x2, y2 = points[j]
x3, y3 = points[k]
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1)
@cache
def dfs(state):
if state == (1 << n) - 1:
return 0
ans = inf
for i in range(n):
if not (state >> i & 1):
for j in range(i + 1, n):
nxt = state | 1 << i | 1 << j
for k in range(j + 1, n):
if not (nxt >> k & 1) and check(i, j, k):
nxt |= 1 << k
ans = min(ans, dfs(nxt) + 1)
if i == n - 1:
ans = min(ans, dfs(state | 1 << i) + 1)
return ans
n = len(points)
return dfs(0)
class Solution {
private int[] f;
private int[][] points;
private int n;
public int minimumLines(int[][] points) {
n = points.length;
this.points = points;
f = new int[1 << n];
return dfs(0);
}
private int dfs(int state) {
if (state == (1 << n) - 1) {
return 0;
}
if (f[state] != 0) {
return f[state];
}
int ans = 1 << 30;
for (int i = 0; i < n; ++i) {
if (((state >> i) & 1) == 0) {
for (int j = i + 1; j < n; ++j) {
int nxt = state | 1 << i | 1 << j;
for (int k = j + 1; k < n; ++k) {
if (((state >> k) & 1) == 0 && check(i, j, k)) {
nxt |= 1 << k;
}
}
ans = Math.min(ans, dfs(nxt) + 1);
}
if (i == n - 1) {
ans = Math.min(ans, dfs(state | 1 << i) + 1);
}
}
}
return f[state] = ans;
}
private boolean check(int i, int j, int k) {
int x1 = points[i][0], y1 = points[i][1];
int x2 = points[j][0], y2 = points[j][1];
int x3 = points[k][0], y3 = points[k][1];
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1);
}
}
class Solution {
public:
int minimumLines(vector<vector<int>>& points) {
auto check = [&](int i, int j, int k) {
int x1 = points[i][0], y1 = points[i][1];
int x2 = points[j][0], y2 = points[j][1];
int x3 = points[k][0], y3 = points[k][1];
return (x2 - x1) * (y3 - y1) == (x3 - x1) * (y2 - y1);
};
int n = points.size();
int f[1 << n];
memset(f, 0, sizeof f);
function<int(int)> dfs = [&](int state) -> int {
if (state == (1 << n) - 1) return 0;
if (f[state]) return f[state];
int ans = 1 << 30;
for (int i = 0; i < n; ++i) {
if (!(state >> i & 1)) {
for (int j = i + 1; j < n; ++j) {
int nxt = state | 1 << i | 1 << j;
for (int k = j + 1; k < n; ++k) {
if (!(nxt >> k & 1) && check(i, j, k)) {
nxt |= 1 << k;
}
}
ans = min(ans, dfs(nxt) + 1);
}
if (i == n - 1) {
ans = min(ans, dfs(state | 1 << i) + 1);
}
}
}
return f[state] = ans;
};
return dfs(0);
}
};
func minimumLines(points [][]int) int {
check := func(i, j, k int) bool {
x1, y1 := points[i][0], points[i][1]
x2, y2 := points[j][0], points[j][1]
x3, y3 := points[k][0], points[k][1]
return (x2-x1)*(y3-y1) == (x3-x1)*(y2-y1)
}
n := len(points)
f := make([]int, 1<<n)
var dfs func(int) int
dfs = func(state int) int {
if state == (1<<n)-1 {
return 0
}
if f[state] > 0 {
return f[state]
}
ans := 1 << 30
for i := 0; i < n; i++ {
if (state >> i & 1) == 0 {
for j := i + 1; j < n; j++ {
nxt := state | 1<<i | 1<<j
for k := j + 1; k < n; k++ {
if (nxt>>k&1) == 0 && check(i, j, k) {
nxt |= 1 << k
}
}
ans = min(ans, dfs(nxt)+1)
}
if i == n-1 {
ans = min(ans, dfs(state|1<<i)+1)
}
}
}
f[state] = ans
return ans
}
return dfs(0)
}