给出圆的圆心和半径,以及三角形的三个顶点,问圆同三角形是否相交。相交输出"Yes",否则输出"No"。(三角形的面积大于0)。
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
分析:转化为求线段离圆心的最近和最远距离。最近距离小于等于r,最远距离大于等于r为相交。
普通版代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #define LL long long 6 using namespace std; 7 double xc, yc, r; 8 int pan(double x1, double y1, double x2, double y2) 9 { 10 double d, d1, d2,maxd,mind; 11 d=fabs((xc-x1)*(y2-y1)-(yc-y1)*(x2-x1))/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));//点到直线距离 12 d1=sqrt((xc-x1)*(xc-x1)+(yc-y1)*(yc-y1)); 13 d2=sqrt((xc-x2)*(xc-x2)+(yc-y2)*(yc-y2));//点到两个端点距离 14 if(((xc-x1)*(x2-x1)+(yc-y1)*(y2-y1))>0&&((xc-x2)*(x1-x2)+(yc-y2)*(y1-y2))>0)//判断点积大于0 15 mind=d; 16 else 17 mind=min(d1,d2); 18 maxd=max(d1,d2); 19 if(fabs(mind-r)<=1e-10||fabs(maxd-r)<=1e-10||(mind<r&&maxd>r)) 20 return 1; 21 else 22 return 0; 23 } 24 int main() 25 { 26 int T; 27 double x1, y1, x2, y2, x3, y3, x, y; 28 scanf("%d", &T); 29 while(T--) 30 { 31 int f=0; 32 scanf("%lf%lf%lf", &xc, &yc, &r); 33 scanf("%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &x3, &y3); 34 f=pan(x1,y1,x2,y2); 35 if(f==0) 36 f=pan(x1,y1,x3,y3); 37 if(f==0) 38 f=pan(x2,y2,x3,y3); 39 if(f==1) 40 printf("Yes\n"); 41 else 42 printf("No\n"); 43 } 44 return 0; 45 }
专业版:
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #define LL long long 6 using namespace std; 7 struct Point 8 { 9 double x, y; 10 Point(double x=0, double y=0):x(x),y(y){} 11 }; 12 Point a[4]; 13 double r; 14 typedef Point Vector; 15 Vector operator-(Point A, Point B){return Vector(A.x-B.x,A.y-B.y);}//向量 16 double Dot(Vector A, Vector B){return A.x*B.x+A.y*B.y;}//点积 17 double Length(Vector A){return sqrt(Dot(A,A));}//向量长度 18 double Cross(Vector A, Vector B){return A.x*B.y-A.y*B.x;}//叉积 19 int pan(Point A, Point B) 20 { 21 double d,d1,d2,maxd,mind; 22 d=fabs(Cross(a[0]-A,B-A))/Length(A-B); 23 d1=Length(a[0]-A); 24 d2=Length(a[0]-B); 25 if(Dot(a[0]-A,B-A)>0&&Dot(a[0]-B,A-B)>0) 26 mind=d; 27 else 28 mind=min(d1,d2); 29 maxd=max(d1,d2); 30 if(fabs(mind-r)<=1e-10||fabs(maxd-r)<=1e-10||(mind<r&&maxd>r)) 31 return 1; 32 else 33 return 0; 34 } 35 int main() 36 { 37 int T; 38 scanf("%d", &T); 39 while(T--) 40 { 41 int f=0; 42 scanf("%lf%lf%lf", &a[0].x, &a[0].y, &r); 43 scanf("%lf%lf%lf%lf%lf%lf", &a[1].x, &a[1].y, &a[2].x, &a[2].y, &a[3].x, &a[3].y); 44 f=pan(a[1],a[2]); 45 if(f==0) 46 f=pan(a[1],a[3]); 47 if(f==0) 48 f=pan(a[2],a[3]); 49 if(f==1) 50 printf("Yes\n"); 51 else 52 printf("No\n"); 53 } 54 return 0; 55 }