我们个人赛的一个题目,简单的计算几何,在聊题目之前,我想先聊聊我的心路历程。。。写了150行斜率和截距判断的函数后,突然发现其实根本不需要。。。然后改叉积就50行就过了,emmmm。
目录
题目链接:
http://codeforces.com/problemset/problem/961/D
题目:
D. Pair Of Lines
time limit per test 2 seconds
memory limit per test 256 megabytes
You are given n points on Cartesian plane. Every point is a lattice point (i. e. both of its coordinates are integers), and all points are distinct.
You may draw two straight lines (not necessarily distinct). Is it possible to do this in such a way that every point lies on at least one of these lines?
Input
The first line contains one integer n (1 ≤ n ≤ 105) — the number of points you are given.
Then n lines follow, each line containing two integers xi and yi (|xi|, |yi| ≤ 109)— coordinates of i-th point. All n points are distinct.
Output
If it is possible to draw two straight lines in such a way that each of given points belongs to at least one of these lines, print YES. Otherwise, print NO.
Examples
input
5 0 0 0 1 1 1 1 -1 2 2
output
YES
input
5 0 0 1 0 2 1 1 1 2 3
output
NO
Note
In the first example it is possible to draw two lines, the one containing the points 1, 3 and 5, and another one containing two remaining points.
题意:
有n个点,问是否存在两条直线,使得所有点都在这两条直线上面。
思路:
首先确定前三个点的情况,因为前三个点就可以确定两条直线的走向了,如果三个点共线,如果出现一个不共线的点就确定了两条直线,如果如果三个点不共线就直接确定了两条直线。所以我们只需要把前三个点任意组合,取两个,然后就判断后面加入的点是否在直线上,用一个标记数组来标记每个点使用的情况,然后取两个不在上面的点,再以他们为基础,将所有不在上面的点,判断一次,就可以判断了。
AC代码:
#include<bits/stdc++.h>
#include<ctime>
using namespace std;
typedef double dl;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long ul;
typedef unsigned long long ull;
const int Mod = 998244353;
const int mod = 1e9 + 7;
const int N = 1e5 + 7;
const int M = 2e6 + 7;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
#define mem(a) memset(a,0,sizeof a)
#define lson l,mid,mid << 1
#define rson mid + 1,r,mid << 1|1
inline ull gcd(unsigned int a,unsigned int b) {return b ? gcd(b,a % b) : a;}
inline ull lcm(unsigned int a,unsigned int b) {return a / gcd(a,b) * b;}
inline double Euler(int n) {return log(n) + 1.0 / (2 * n) + 0.57721566490153286060651209;}
//inline ll inverse_feima(ll n) {return fpow_mod(n,mod - 2);}
struct point{
ll x,y;
}p[N];
int n;
bool is[N];
inline bool judge(point a,point b,point c)
{
return (b.y - a.y) * (c.x - b.x) == (c.y - b.y) * (b.x - a.x);
}
bool check(int a,int b){
memset(is,false,sizeof is);
for(int i = 1;i <= n;++i) if(judge(p[a],p[b],p[i])) is[i] = true;
int res1 = -1,res2 = -1;
for(int i = 1;i <= n;++i){
if(!is[i]){
if(res1 == -1) res1 = i;
else res2 = i;
}
}
if(res1 == -1 || res2 == -1) return true;
for(int i = 1;i <= n;++i)
if(!is[i] && !judge(p[res1],p[res2],p[i])) return false;
return true;
}
int main()
{
//ios::sync_with_stdio(false)'
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d",&n);
for(int i = 1;i <= n;++i) scanf("%lld%lld",&p[i].x,&p[i].y);
if(n <= 4) printf("YES\n");
else{
if(check(1,2) || check(1,3) || check(2,3)) printf("YES\n");
else printf("NO\n");
}
return 0;
}