CodeForces - 961D——(计算几何——叉积的运用)

本文解决了一个计算几何问题,探讨如何通过判断点是否共线来确定是否存在两条直线覆盖所有给定点。介绍了题目的背景、思路及AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们个人赛的一个题目,简单的计算几何,在聊题目之前,我想先聊聊我的心路历程。。。写了150行斜率和截距判断的函数后,突然发现其实根本不需要。。。然后改叉积就50行就过了,emmmm。

目录

题目链接:

题目:

题意:

思路:

AC代码:


题目链接:

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值