题目链接
问题:
给出圆的圆心和半径,以及三角形的三个顶点,
圆同三角形是否相交。相交输出"Yes",否则输出"No"。
Input
第1行:一个数T,表示输入的测试数量(1 <= T <= 10000),之后每4行用来描述一组测试数据。 4-1:三个数,前两个数为圆心的坐标xc, yc,第3个数为圆的半径R。(-3000 <= xc, yc <= 3000, 1 <= R <= 3000) 4-2:2个数,三角形第1个点的坐标。 4-3:2个数,三角形第2个点的坐标。 4-4:2个数,三角形第3个点的坐标。(-3000 <= xi, yi <= 3000)
Input示例
2 0 0 10 10 0 15 0 15 5 0 0 10 0 0 5 0 5 5
Output示例
Yes No
分析:
1.当三个点都在园内时,一定是NO
2.当三个点都在圆外时,判断 圆心到 线段的距离,这里需要分情况谈论
判断圆心与线段构成的三角形
如果圆外的两个角有一个是钝角,那么一定不相交
如果都是锐角,可以用海伦公式求点到线段的距离
3.一定是YES,因为只剩下一种情况,既有圆内又有圆外的点
这里还卡了精度,!!!!!! 浮点数 比较,很烦人,
引入了 eps ~~~~~
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
double cx,cy,r;
double dist(double x1,double y1,double x2,double y2)
{
double d=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
return d;
}
// 判断线段于圆的位置关系(前提是所有点在圆外)
int line_pan(double x1,double y1,double x2,double y2)
{
double a,b,c;
a = dist(cx,cy,x1,y1);
b = dist(cx,cy,x2,y2);
c = dist(x1,y1,x2,y2);
// 线段过圆心
if((a+b) == c)
return 1;
// 线段的延长线过圆心,因为点在圆外,所以不相交
if(a==b+c || b==a+c)
return 0;
// 圆外的叫是钝角的情况不能用海伦公式,因为此时点到线段最短距离不是高
if(a*a >= (b*b+c*c) || b*b >= (a*a+c*c))
return 0;
// 圆外的角不是钝角的情况可以用海伦公式i
double l=(a+b+c)/2;
double s=sqrt(l*(l-a)*(l-b)*(l-c));
double d=2*s/c;
if(d - r <= 0.00001) // 精度 问题
return 1;
else
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
double ans1,ans2,ans3;
// 输入圆心和半径
scanf("%lf%lf%lf",&cx,&cy,&r);
// 第一个点道远新的距离
double x1,y1;
scanf("%lf%lf",&x1,&y1);
ans1 = dist(x1,y1,cx,cy);
// 第二个点到圆心的距离
double x2,y2;
scanf("%lf%lf",&x2,&y2);
ans2 = dist(x2,y2,cx,cy);
// 第三个点到圆心的距离
double x3,y3;
scanf("%lf%lf",&x3,&y3);
ans3 = dist(x3,y3,cx,cy);
// 如果三点都在圆内
if(ans1<r && ans2<r && ans3<r)
printf("No\n");
// 如果三点都在圆外
else if(ans1>r && ans2>r && ans3>r)
{
if(line_pan(x1,y1,x2,y2)||line_pan(x3,y3,x2,y2)||line_pan(x1,y1,x3,y3))
printf("Yes\n");
else
printf("No\n");
}
// 有在内的点,也有在外的点
else
printf("Yes\n");
}
return 0;
}