51Nod 1298:圆与三角形(计算几何)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1298

题目给出一个圆的圆心坐标和半径,再给出三角形三点坐标。判断三角形与圆是否相交,相交的话输出Yes,相离输出No.

非常简单的一个几何题目。

很容易想到如果三角形三点距圆心的距离都小于半径,则三角形在圆内,没有交点。

如果三角形三点距圆心的距离都大于半径,此时圆心到三角形三边的距离要大于半径。

不过做的时候WA到吐血,狂WA第三组测试数据,奔溃掉。


然后百度别人的博客想看看自己坑到哪里了,发现他们先求直线方程又求焦点,又判断

焦点是否在线段上,然后再弄。好麻烦的做法,直接用点到线段距离公式不就好了,看

不下去了,后来无奈把第三组数据的输入和输出都下载下来了,一侧才发现,其中有一

组相切的情况,竟然给我判了相离,才发现计算过程更中精度缺失,所以加了个eps,

距离减去r>eps,才判距离大于半径。才过了。


用点到线段距离做炒鸡简单的。求法如图所示:

声明:以下求法只针对三点构成三角形的情况,并没有去考虑,AB非常近,或ABP三点共线这种

情况。


代码模板:

///求点到线段的最短距离。
double getNearestDistance(double x1,double y1,double x2,double y2,double x,double y)
{
    double a = getDistance(x1,y1,x,y);
    double b = getDistance(x2,y2,x,y);
    double c = getDistance(x1,y1,x2,y2);
    if(a*a>=b*b+c*c)
        return b;
    if(b*b>=a*a+c*c)
        return a;
    double L = (a+b+c)/2;
    double S = sqrt(L*(L-a)*(L-b)*(L-c));
    return 2*S/c;
}

题目AC代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define eps 1e-6

using namespace std;

///求两点直接距离。
double getDistance(double x1,double y1,double x2,double y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
///求点到线段的最短距离。
double getNearestDistance(double x1,double y1,double x2,double y2,double x,double y)
{
    double a = getDistance(x1,y1,x,y);
    double b = getDistance(x2,y2,x,y);
    double c = getDistance(x1,y1,x2,y2);
    if(a*a>=b*b+c*c)
        return b;
    if(b*b>=a*a+c*c)
        return a;
    double L = (a+b+c)/2;
    double S = sqrt(L*(L-a)*(L-b)*(L-c));
    return 2*S/c;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        double x,y,r;              ///圆心和半径
        double x1,y1,x2,y2,x3,y3;  ///三角形三点坐标
        double dis1,dis2,dis3,dis4,dis5,dis6;
        scanf("%lf%lf%lf",&x,&y,&r);
        scanf("%lf%lf",&x1,&y1);
        scanf("%lf%lf",&x2,&y2);
        scanf("%lf%lf",&x3,&y3);
        dis1 = getDistance(x,y,x1,y1);               ///点1到圆心的距离
        dis2 = getDistance(x,y,x2,y2);               ///点2到圆心的距离
        dis3 = getDistance(x,y,x3,y3);               ///点3到圆心的距离
        dis4 = getNearestDistance(x1,y1,x2,y2,x,y);  ///圆心到点1点2组成线段的距离
        dis5 = getNearestDistance(x1,y1,x3,y3,x,y);  ///圆心到点1点3组成线段的距离
        dis6 = getNearestDistance(x2,y2,x3,y3,x,y);  ///圆心到点2点3组成线段的距离
        /*不用epsWA到死*/
        if(dis4-r>eps && dis5-r>eps && dis6-r>eps)   ///三点在圆外且圆心到三角形三边距离大于r,没交点 
            printf("No\n");
        else if(dis1<r && dis2<r && dis3<r)          ///三点在圆内,一定没有交点,
            printf("No\n");
        else
            printf("Yes\n");                         ///三点中有在圆外的点,有在圆内的点。
    }
    return 0;
}

/*
第三组数据及其答案
30
9 3 7
-1 -3
5 -6
4 8
3 1 9
-2 -10
0 7
-5 -5
4 -7 3
7 -7
7 0
5 -1
-2 -2 2
5 -4
-3 -3
-9 2
-9 -1 8
-8 -9
-7 -4
-4 1
-5 9 4
-10 7
-2 6
-10 -8
3 -6 9
9 -5
-2 -9
-5 -1
8 -10 4
9 -4
-1 -2
0 -5
-1 6 1
8 -9
4 -6
-9 -2
6 -4 9
7 7
-1 7
-10 1
-3 3 9
2 -8
-2 5
-7 -10
-7 3 1
-8 -7
-3 9
-8 7
-1 5 3
-2 2
7 9
-3 -1
-7 1 2
-1 -8
-7 -3
9 -9
9 -3 1
9 5
5 -3
7 3
3 8 5
7 -10
-9 7
-10 7
-6 9 5
-2 4
-2 -2
3 -2
-5 -8 3
9 7
-4 -10
6 5
4 -9 2
-6 9
-10 -4
-8 -9
7 4 3
9 9
-9 -4
-2 -5
0 2 6
8 -6
9 -5
2 1
4 1 9
0 2
-2 9
-3 3
-8 -9 3
-4 -10
3 -9
7 7
7 -4 7
6 4
-1 4
-4 8
4 3 7
-3 4
-9 1
6 -1
-1 2 3
-5 -2
6 -1
3 8
-3 -4 7
6 9
-10 -3
2 -2
4 -9 2
-3 2
-2 8
-8 -10
-6 1 8
7 4
2 2
1 0
-5 7 6
1 -10
6 -2
-9 -3
*/

/*
Yes
Yes
Yes
Yes
Yes
Yes
Yes
No
No
No
Yes
Yes
Yes
No
No
No
No
Yes
No
Yes
Yes
Yes
No
No
Yes
Yes
Yes
No
Yes
No
*/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值