1298 圆与三角形
给出圆的圆心和半径,以及三角形的三个顶点,问圆同三角形是否相交。相交输出"Yes",否则输出"No"。(三角形的面积大于0)。
![](http://img.51nod.com/upfile/000fbd56/08d1bc4455418997000000000000000c.jpeg)
![](http://img.51nod.com/upfile/000fbd56/08d1bc445a06ab83000000000000000d.jpeg)
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)
Output
共T行,对于每组输入数据,相交输出"Yes",否则输出"No"。
Input示例
2 0 0 10 10 0 15 0 15 5 0 0 10 0 0 5 0 5 5
Output示例
Yes No
/* 圆与三角形是否相交,转化为线段与圆相交 1.两点都在圆内 --相离 2.一点在圆内,一点在圆外 --相交 3.两点都在圆外 ① .如果圆心到线段所在直线的距离>r --相离 ② .距离<=r 如果圆心与线段两个端点以及线段本身组成的夹角都是锐角 --相交 否则 --相离 */ #include <bits/stdc++.h> #define MAXK 5 using namespace std; struct Point{ double x,y; Point(){} Point(double _x,double _y){ x=_x; y=_y; } }; int t; double a,b,r; Point p[MAXK],O; bool ok; int judge(Point *p1, Point *p2,double r) {//点p1和p2都不在圆内 double a, b, c, dist1, dist2, angle1, angle2; // ax + by + c = 0; if (p1->x == p2->x) a = 1, b = 0, c = -p1->x;//特殊情况判断,分母不能为零 else if (p1->y == p2->y) a = 0, b = 1, c = -p1->y;//特殊情况判断,分母不能为零 else { a = p1->y - p2->y; b = p2->x - p1->x; c = p1->x * p2->y - p1->y * p2->x; } dist1 = a * O.x + b * O.y + c; dist1 *= dist1; dist2 = (a * a + b * b) * r * r; if (dist1 > dist2) return 0;//点到直线距离大于半径r angle1 = (O.x - p1->x) * (p2->x - p1->x) + (O.y - p1->y) * (p2->y - p1->y); angle2 = (O.x - p2->x) * (p1->x - p2->x) + (O.y - p2->y) * (p1->y - p2->y); if (angle1 > 0 && angle2 > 0) return 1;//余弦都为正,则是锐角 return 0; } inline void init(){ ok=false; } int main(){ // freopen("in.txt","r",stdin); scanf("%d",&t); while(t--){ init(); scanf("%lf%lf%lf",&a,&b,&r); O.x=a; O.y=b; int flag1=0;//圆上 int flag2=0;//圆外 int flag3=0;//圆内 for(int i=0;i<3;i++){ scanf("%lf%lf",&p[i].x,&p[i].y); if((a-p[i].x)*(a-p[i].x)+(b-p[i].y)*(b-p[i].y)==r*r) flag1++; else if((a-p[i].x)*(a-p[i].x)+(b-p[i].y)*(b-p[i].y)>r*r) flag2++; else flag3++; } if(flag1!=0){//有在圆上的 puts("Yes"); continue; }else if(flag2!=0&&flag3!=0){//有在内也有在外的 puts("Yes"); continue; }else if(flag2==0&&flag3!=0){//全部在圆内 puts("No"); continue; }else{//都在圆外就要讨论了 for(int i=0;i<3;i++){ if(judge(&p[i%3],&p[(i+1)%3],r)==true){ ok=true; break; } } if(ok==false){ puts("No"); }else{ puts("Yes"); } } } return 0; }
我每天都在努力,只是想证明我是认真的活着.