(计算几何)
题意:给出n个点的坐标(x,y),问你是否能用2条直线过所有点,可以输出YES,反之NO。
解法:对于这种情况,那我们当n<=4是一定成立的,n>4的时候我们可以任意取3个点,先以3点中的2点画一条直线,把该直线不能过的点存入vector中,在对剩下的所有点进行判断,它们是否都在一条直线上,是的话输出YES,不是则取3点中其他2点重复进行上步骤,直到3种情况都没办法实现,那么可以输出NO了。(其实就是一个散点图中,若能用2条直线覆盖所有点,那么容易取三点中的2点必然与其中一条直线重合,复杂问题简单化)
代码如下:
#include <stdio.h> #include <string> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include<map> #include<vector> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int maxn = 1e5 + 500; struct node { ll x, y; }a[maxn]; bool Xmult(node p1, node p2, node p0) { return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y) == 0 ? true : false; } int n; int vis[maxn]; bool fun() { vector<int>q; int key = 1; for (int i = 2; i < n; i++) if (!Xmult(a[0], a[1], a[i]))q.push_back(i); if (q.size() <= 2)return true; for (int i = 2; i < q.size(); i++) if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) { key = 0; break; } if (key)return true; q.clear(); key = 1; for (int i = 1; i < n; i++) if (!Xmult(a[0], a[2], a[i]))q.push_back(i); if (q.size() <= 2)return true; for (int i = 2; i < q.size(); i++) if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) { key = 0; break; } if (key)return true; q.clear(); key = 1; for (int i = 0; i < n; i++) if (!Xmult(a[1], a[2], a[i]))q.push_back(i); if (q.size() <= 2)return true; for (int i = 2; i < q.size(); i++) if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) { key = 0; break; } if (key)return true; return false; } int main() { cin >> n; for (int i = 0; i < n; i++) scanf("%lld%lld", &a[i].x, &a[i].y); if (n<=4||fun()) cout << "YES" << endl; else cout << "NO" << endl; return 0; }