三点共线

题目描述

在二维平面上给定多个点,判断是否存在三个点共线

基本思想

在给定的点中,任意取出三个点 p1,p2,p3 ,一共有 C3n 中情况,只要存在一组三点共线,即可确定存在三个点共线,反之,不存在三点共线。

线

根据直线两点式: yy1xx1=y2y1x2x1 ,只要 p1(x1,y1),p2(x2,y2),p3(x3,y3) 满足下式时,便可判定三点共线:


(y3y1)(x2x1)(y2y1)(x3x1)=0

但由于在计算机中小数会有一定的误差,尽量不要用“==”进行比较,应该取一定的误差,例如

|(y3y1)(x2x1)(y2y1)(x3x1)|<=106

// 判断三点共线函数的实现
// 共线返回1
// 不共线返回0
int on_a_line(point a, point b, point c)
{
    float tempy1 = (a.y - b.y) ;
    float tempx1 = (a.x - b.x);
    float tempy2 = (c.y - a.y) ;
    float tempx2 = (c.x - a.x);
    float xp = tempy1 * tempx2;
    float yp = tempy2 * tempx1;
    if(fabs(xp - yp) <= 1e-6)
        return 1;
    else
        return 0;
}
#include<stdio.h>
#include<math.h>
// 定义坐标点
typedef struct point
{
    float x;
    float y;
}point;
// 三点共线判断函数
// 共线返回1
// 不共线返回0
int on_a_line(point a, point b, point c);
int main()
{
    // 定义测试次数
    int case_num = 0;
    // 定义点数
    int point_num = 0;
    // 共线标志,1共线,0不共线
    int flag = 0;
    int i,j,k,l;
    // 输入测试次数
    scanf("%d",&case_num);
    for(i = 0; i < case_num; i++)
    {
        // 输入坐标数
        scanf("%d",&point_num);
        // 声明坐标数组
        point points[point_num];
        // 输入坐标
        for(j = 0; j < point_num; j++)
        {
            // 输入横坐标x
            scanf("%f",&points[j].x);
            // 输入纵坐标y
            scanf("%f",&points[j].y);
        }
        // 判断是否存在三点共线 
        if(point_num >= 3)
        {
            for(j = 0 ;j < point_num && flag == 0; j++)
            {
                for(k = j + 1; k < point_num && flag == 0; k++)
                {
                    for(l = k + 1; l < point_num && flag == 0; l++)
                    {
                        if(on_a_line(points[j],points[k],  points[l]))
                            flag = 1;
                    }
                }
            }
            // 打印信息
            if(flag == 1)
            {
                printf("Yes\n");
                flag = 0;
            }
            else
                printf("No\n");
        }
    }
}
// 判断三点共线函数的实现
int on_a_line(point a, point b, point c)
{
    float tempy1 = (a.y - b.y) ;
    float tempx1 = (a.x - b.x);
    float tempy2 = (c.y - a.y) ;
    float tempx2 = (c.x - a.x);
    float xp = tempy1 * tempx2;
    float yp = tempy2 * tempx1;
    if(fabs(xp - yp) <= 1e-6)
        return 1;
    else
        return 0;
}
### 天梯赛中的三点共线问题解题思路 在解决天梯赛中的三点共线问题时,核心在于如何判断三个点是否位于同一条直线上。通常可以通过计算斜率或者向量叉积来完成这一目标。 #### 判断方法一:利用斜率 如果给定的三个点分别为 \(A(x_1, y_1)\),\(B(x_2, y_2)\),以及 \(C(x_3, y_3)\),则可以通过验证任意两点之间的斜率是否相等来进行判断。具体来说: \[ k_{AB} = \frac{y_2 - y_1}{x_2 - x_1}, \quad k_{BC} = \frac{y_3 - y_2}{x_3 - x_2} \] 当且仅当 \(k_{AB} = k_{BC}\) 时,这三个点才共线[^1]。然而,在实际编码过程中需要注意浮点数精度误差的影响,因此推荐改用整型运算替代除法操作。例如,通过交叉乘积的方式重写条件为: \[ (y_2 - y_1)(x_3 - x_2) = (y_3 - y_2)(x_2 - x_1) \] 这样可以有效避免因浮点数比较带来的潜在错误。 #### 判断方法二:利用向量叉积 另一种更为通用的方法是基于向量叉积的概念。对于两个向量 \(\vec{v_1} = B-A\) 和 \(\vec{v_2} = C-B\) 而言,其叉积定义如下: \[ \text{Cross Product} = (\vec{v_1}_x * \vec{v_2}_y) - (\vec{v_1}_y * \vec{v_2}_x) \] 其中, \[ \vec{v_1}_x = x_2 - x_1,\; \vec{v_1}_y = y_2 - y_1, \] \[ \vec{v_2}_x = x_3 - x_2,\; \vec{v_2}_y = y_3 - y_2. \] 若该叉积的结果等于零,则说明这两个向量平行于同一平面内的某条直线,即三者共线[^2]。 以下是采用第二种方式实现的一个Python代码示例: ```python def is_collinear(p1, p2, p3): # 计算两组差值作为向量坐标 v1_x, v1_y = p2[0]-p1[0], p2[1]-p1[1] v2_x, v2_y = p3[0]-p2[0], p3[1]-p2[1] cross_product = v1_x * v2_y - v1_y * v2_x return abs(cross_product) < 1e-9 # 浮点数容忍度处理 # 示例调用 point_a = (0, 0) point_b = (1, 1) point_c = (2, 2) print(is_collinear(point_a, point_b, point_c)) # 输出 True 表明共线 ``` 以上两种方法各有优劣,但在竞赛环境中建议优先考虑后者——向量叉积法,因为它不仅逻辑清晰而且无需担心分母为零的情况发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值