版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/V5ZSQ/article/details/82453398
Description
给出一个大圆和 个不相交小圆,问该大圆删去与小圆分割部分后的外围周长
Input
第一行一整数 表示用例组数,每组用例首先输入两个整数 表示小圆个数和大圆半径(大圆圆心在原点),之后 行每行输入三个整数 表示该小圆的圆心坐标和半径
Output
输出大圆删去与小圆分割部分后的外围周长
Sample Input
1
4 10
6 3 5
10 -4 3
-2 -4 4
0 9 1
Sample Output
81.62198908430238475376
Solution
任意两个小圆相离,答案即为大圆周长加上每个小圆对周长的影响,只要一个小圆与大圆相交,则该小圆的影响即为删去大圆这部分周长然后加上小圆位于大圆内的周长
Code
#include<cstdio>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define eps 1e-8
struct circle
{
double x,y,r;
}p[101];
int sgn(double x)
{
if(fabs(x)<eps)return 0;
if(x>eps)return 1;
return -1;
}
double Solve(circle a,circle b)
{
double d=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
if(sgn(d-a.r-b.r)>=0)return 0;//相离或外切
if(sgn(a.r-d-b.r)>0)return 0;//内含
if(sgn(a.r-d-b.r)==0)return 2.0*PI*b.r;
//相交
double a1=2.0*acos((a.r*a.r+d*d-b.r*b.r)/(2.0*a.r*d));
double a2=2.0*acos((b.r*b.r+d*d-a.r*a.r)/(2.0*b.r*d));
return a2*b.r-a1*a.r;
}
int T,n;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%lf",&n,&p[0].r);
p[0].x=p[0].y=0;
for(int i=1;i<=n;i++)scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].r);
double ans=2.0*PI*p[0].r;
for(int i=1;i<=n;i++)ans+=Solve(p[0],p[i]);
printf("%.9f\n",ans);
}
return 0;
}