您的位置:首页 > 编程语言 > C语言/C++

圆与三角形-51NOD 1298

2017-04-19 03:06 260 查看
这几天又没怎么学习,懒癌末期啊真的是。

被一道圆与三角形的基础题难倒了,很烦,发现自己数学不好。

这个问题牵扯到线段和点的距离判断。

分三种情况

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 acm 算法基础