D. Pair Of Lines
题目大意:
给n个点,问是否存在两条直线(可以为同一条)能覆盖所有的点。
解题思路:
首先一个或者两个或者三个点都是肯定可以用两条线覆盖的。
如果点的个数大于等于三个,那么我们已经可以确定至少一条线的:
点1和点2可能在一条线上,点2和点3可能在一条线上,点3和点1可能在一条线上。
我们试着确定其中一条线后,去掉在线上的所有点,剩下的点肯定在另一条线上,这样利用剩下的点就可以确定另一条直线。
能找到这两条线输出"YES",否则,如果大于等于3条线,输出"NO".
代码:
using namespace std; typedef long long LL; const int MAXN = 100000 + 10; typedef pair<int, int> pii; pii p[MAXN]; bool fir[MAXN]; int n; inline pii operator-(const pii& a, const pii& b) { return make_pair(a.first - b.first, a.second - b.second); } inline LL cross(const pii& a, const pii& b) { return 1LL * a.first * b.second - 1LL * a.second * b.first; } bool check(const pii& a, const pii& b) { memset(fir, 0, sizeof fir); for (int i = 0; i < n; i++) { if (cross(b - a, p[i] - a) == 0) fir[i] = 1; } int p1 = -1, p2 = -1; for (int i = 0; i < n; i++) if (!fir[i]) { if (p1 == -1) p1 = i; else if (p2 == -1) p2 = i; } if (p2 == -1) return true; else { for (int i = 0; i < n; i++) if (!fir[i]) { if (cross(p[p2] - p[p1], p[i] - p[p1]) != 0) return false; } return true; } } int main() { while (cin >> n) { for (int i = 0; i < n; i++) { cin >> p[i].first >> p[i].second; } if (n == 1 || n == 2 || n == 3) cout << "YES\n"; else { if (check(p[0], p[1]) || check(p[1], p[2]) || check(p[0], p[2])) { cout << "YES\n"; } else { cout << "NO\n"; } } } return 0; }