HDU 6354 Everything Has Changed(计算几何)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/V5ZSQ/article/details/82453398

Description

给出一个大圆和 n 个不相交小圆,问该大圆删去与小圆分割部分后的外围周长

Input

第一行一整数 T 表示用例组数,每组用例首先输入两个整数 n , R 表示小圆个数和大圆半径(大圆圆心在原点),之后 n 行每行输入三个整数 x , y , r 表示该小圆的圆心坐标和半径

( 1 T 1000 , 1 n 100 , 1000 x , y 1000 , 0 < r , R 1000 )

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;
}

猜你喜欢

转载自blog.csdn.net/V5ZSQ/article/details/82453398
今日推荐