圆与三角形-51NOD 1298

这几天又没怎么学习,懒癌末期啊真的是。
被一道圆与三角形的基础题难倒了,很烦,发现自己数学不好。
这个问题牵扯到线段和点的距离判断。
分三种情况
1. 点P到直线的距离等于点P到端点A的距离。
2. 点P到直线的距离等于点P到端点B的距离。
3. 点P到直线的距离等于点P到投影点C的距离。
设向量AP,向量AB。
AP与AB的余弦cos=AP·AB/|AP||AB|
若cos<0则是第一种情况了 我们return AP;
else 我们进行下一步运算
{
AC=AP*cos;
if(AC>AB)
return PB;
else
return PC;
}
然后找到圆心与三条边的最大值与最小值

if((max>r&&max<r)||max==r||min==r)
就YES啊
else就NO咯

然后悲剧地发现WA了
因为没有想到如果三条边与圆心的距离都小于r,但三个顶点与圆心的距离大于r的情况。
加进去,再交,再WA。
就很气。
检查数据之后发现这种几何题目需要加入精度控制。
于是又写了一个sgn

int sgn(double a)
{
    return a<-eps?-1:a<eps?0:1;
}

千辛万苦终于是AC了

//#define Debug
#include <stdio.h>
#include <math.h>

#define MAXN 100001
#define INF 0x3f3f3f3f
#define MIN(a,b) a>b?b:a
#define MAX(a,b) a>b?a:b
#define eps 1e-6

int cx,cy,r;
int x[3],y[3];

int sgn(double a)
{
    return a<-eps?-1:a<eps?0:1;
}

double f(double a)
{
    return a*a;
}

double point(int i)
{
    return sqrt((x[i]-cx)*(x[i]-cx)+(y[i]-cy)*(y[i]-cy));
}

double line(int a,int b)
{
    double apl=point(a),abl=sqrt(f(x[a]-x[b])+f(y[a]-y[b]));
    double cos=((cx-x[a])*(x[b]-x[a])+(y[b]-y[a])*(cy-y[a]))/apl/abl;
    if(cos<=0)
    {
        return apl;
    }
    else
    {
        double acl=apl*cos;
        if(acl>abl)
            return point(b);
        else
            return sqrt(f(apl)-f(acl));
    }
}

int main()
{
#ifdef Debug
    freopen("C:\\Users\\Yemor\\Desktop\\read.txt","r",stdin);
#endif
    int T;
    double min,max,tmp;
    scanf("%d",&T);
    while(T--)
    {
        min=INF;
        max=-INF;
        scanf("%d%d%d",&cx,&cy,&r);
        for (int i = 0; i < 3; ++i)
        {
            scanf("%d%d",&x[i],&y[i]);
        }
        for (int i = 0; i < 3; ++i)
        {
            tmp=point(i);
            max=MAX(max,tmp);
        }
        for (int i = 0; i < 3; ++i)
        {
            if(i!=2)
            {
                tmp=line(i,i+1);
            }
            else
            {
                tmp=line(i,0);
            }
            min=MIN(min,tmp);
            max=MAX(max,tmp);
        }
        if((sgn(max-r)>0&&sgn(min-r)<0)||sgn(max-r)==0||sgn(min-r)==0)
            printf("%s\n","Yes" );
        else
            printf("%s\n","No" );
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值