AtCoder题解—— AtCoder Beginner Contest 181 —— C - Collinearity

该博客围绕AtCoder Beginner Contest 181 C题展开,题目是给定N组坐标,判断是否存在三个不同点共线。题解指出这是数学题,可通过特定公式判断三点共线,因数据范围,用int即可,算法设计采用暴力枚举,虽非最优但简单。

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

题目相关

题目链接

AtCoder Beginner Contest 181 C 题,https://atcoder.jp/contests/abc181/tasks/abc181_c

Problem Statement

We have N points on a two-dimensional infinite coordinate plane.

The ii-th point is at (xi,yi).

Is there a triple of distinct points lying on the same line among the N points?

Input

Input is given from Standard Input in the following format:

N
x1 y1
.
.
.
xN yN

Output

If there is a triple of distinct points lying on the same line, print Yes; otherwise, print No.

Samples1

Sample Input 1

4
0 1
0 2
0 3
1 1

Sample Output 1

Yes

Explaination

The three points (0,1),(0,2),(0,3) lie on the line x=0.

Samples2

Sample Input 2

14
5 5
0 1
2 5
8 0
2 1
0 0
3 6
8 6
5 9
7 9
3 4
9 2
9 8
7 2

Sample Output 2

No

Samples3

Sample Input 3

9
8 2
2 3
1 3
3 7
1 0
8 8
5 6
9 7
0 1

Sample Output 3

Yes

Constraints

  • All values in input are integers.
  • 3≤N≤10^2
  • |xi|,|yi|≤10^3
  • If i≠j, (xi,yi)≠(xj,yj).

题解报告

题目翻译

给 N 组坐标,判断这些坐标中,是否存在三个不同点处于同一条直线。如果存在,输出 Yes,否则输出 No。

题目分析

本题是一个数学题,假设我们有三个点,坐标分别为:点 A 为 (x1, y1)、点 B 为 (x2, y2) 和点 C 为 (x3, y3)。

判断三点共线

假设这三个点共线,则 \left | \frac{y_2-y_1}{x_2-x_1} \right |=\left | \frac{y_3-y_1}{x_3-x_1}\right |。这样我们可以变换为 (y_2-y_1)*(x_3-x_1)= (y_3-y_1)*(x_2-x_1)

数据范围估计

本题的数据范围为 |xi|,|yi|≤10^3,因此最大的数据也就是(10^3-10^{-3})*(10^3-10^{-3})\approx 10^3*10^3=10^6,使用 int 足够。

算法设计

再次强调一下,在算法竞赛中设计算法,需要根据题目的数据规模来设计。

以本题为例,N 的最大值为 10^2,因此完全可以使用暴力枚举来实现,也就是直接枚举是否有三个点,满足条件即可。

这样设计的算法肯定不是最优的,因为时间复杂度为恐怖的 O(N^3),但是一定是最简单的算法。

AC 参考代码

//https://atcoder.jp/contests/abc181/tasks/abc181_c
//C - Collinearity
#include <iostream>

using namespace std;

typedef struct _POS {
    int x;
    int y;
} POS;

const int MAXN=1e2+4;
POS arr[MAXN];

int main() {
    int n;
    cin>>n;
    for (int i=1; i<=n; i++) {
        cin>>arr[i].x>>arr[i].y;
    }

    //暴力枚举
    for (int i=1; i<=n-2; i++) {
        for (int j=i+1; j<=n-1; j++) {
            for (int k=j+1; k<=n; k++) {
                if ((arr[k].x-arr[i].x)*(arr[j].y-arr[i].y)==(arr[j].x-arr[i].x)*(arr[k].y-arr[i].y)) {
                    cout<<"Yes\n";
                    return 0;
                }
            }
        }
    }
    cout<<"No\n";

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值