题目
题意:
给定n个点,输出是否这些点可以至多用两条直线就可以连接。
1
≤
n
≤
1
0
5
,
∣
x
i
∣
,
∣
y
i
∣
≤
1
0
9
1 ≤ n ≤ 10^5,|x_i|, |y_i| ≤ 10^9
1 ≤ n ≤ 105,∣xi∣, ∣yi∣ ≤ 109
分析:
由于一共只有两条线,而且两点确定一条直线。假设答案存在,那么随便拿出三个点,必然有一条直线穿过某两个点。一共三种情况将第一条直线确定下来。
对于别的点来说,如果这个点不在这条直线上,那么必然形成新的直线,再度模拟一下即可。对于一条直线,我们只需要维护在他上面的两个点即可。判断是否在直线上直接判斜率是否相等。
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
struct point{
ll x,y;
}p[100005];
int vis[100005];
ll x1,y1,x2,y2,x3,y3,x4,y4;
int flag3,flag4;
int n;
bool slove(int a1,int a2)
{
x1 = p[a1].x,y1 = p[a1].y;
x2 = p[a2].x,y2 = p[a2].y;
flag3 = flag4 = 0;
memset(vis,0,sizeof(vis));
vis[a1] = vis[a2] = 1;
for (int i = 1; i <= n; i++)
{
if( vis[i] ) continue;
if( (p[i].y - y1 ) * (x2 - x1) == ( p[i].x - x1) * (y2-y1) ) continue;
else if( flag3 == 0 ) x3 = p[i].x,y3 = p[i].y,flag3 = 1;
else if( flag4 == 0 ) x4 = p[i].x,y4 = p[i].y,flag4 = 1;
else if( ( p[i].y - y3 ) * ( x4 - x3 ) == ( p[i].x - x3 ) * ( y4 - y3 ) ) continue;
else return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> p[i].x >> p[i].y;
}
if( n <= 3 )
{
cout << "YES" << '\n';
return 0;
}
if( slove(1,2) || slove(1,3) || slove(2,3) ) cout << "YES" << '\n';
else cout << "NO" << '\n';
return 0;
}