传送门
题意: 给定n个二维平面上的点, 问这些点是否存在于两条直线上.. (如果还对题意比较迷, 那就再说一种那就是所有点共线时也是YES)
思路: 首先, 如果点数<3, 很明显是YES, 所以当点数大于3时我们只需要对前面三个点进行判断就是了, 假设以第一个点和第二个点确定一条直线, 此时我们先把在这条直线上的点先去除, 可以利用向量来判断三点是否共线, 很方便. 然后判断剩下的点是否能构成另一条直线即可, 如果不仅能再去判断第一个和第三个, 第二个和第三个, 以同样的方法….. 注意看清楚题意!…
具体细节请看代码实现.
AC Code
const int maxn = 1e5+5;
struct point {
int x, y;
}p[maxn];
int n;
bool vis[maxn];
point operator - (const point &a, const point &b) {
return point{a.x - b.x, a.y - b.y};
}
ll corss(point a, point b) {
return 1ll*a.x * b.y - 1ll*b.x * a.y;
}
bool check() {
int p1 = -1, p2 = -1;
for (int i = 1 ; i <= n ; i ++) {
if (vis[i]) continue;
if (p1 == -1) p1 = i;
else if (p2 == -1) p2 = i;
}
if (p2 == -1) return true;
for (int i = 1 ; i <= n ; i ++) {
if (vis[i]) continue;
if (corss(p[p1] - p[p2], p[i] - p[p1])) return false;
}
return true;
}
bool ok(point a, point b) {
Fill(vis, 0);
for (int i = 1 ; i <= n ; i ++) {
if (!corss(b - a, p[i] - a)) vis[i] = 1;
}
return check();
}
void solve()
{
while(~scanf("%d", &n)) {
for (int i = 1 ; i <= n ; i ++) {
scanf("%d%d", &p[i].x, &p[i].y);
}
if (n < 3) {
printf("YES\n");
continue ;
}
if (ok(p[1], p[2]) || ok(p[1], p[3]) || ok(p[2], p[3]))
printf("YES\n");
else printf("NO\n");
}
}