欢迎访问https://blog.csdn.net/lxt_Lucia~~
宇宙第一小仙女\(^o^)/~~萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗~~
----------------------------------------我只是一条可爱哒分界线-------------------------------------------
一、问题:
Description
Edward is a worker for Aluminum Cyclic Machinery. His work is operating mechanical arms to cut out designed models. Here is a brief introduction of his work.
Assume the operating plane as a two-dimensional coordinate system. At first, there is a disc with center coordinates (0,0) and radius R. Then, mm mechanical arms will cut and erase everything within its area of influence simultaneously, the i-th area of which is a circle with center coordinates (xi,yi) and radius riri (i=1,2,⋯,m). In order to obtain considerable models, it is guaranteed that every two cutting areas have no intersection and no cutting area contains the whole disc.
Your task is to determine the perimeter of the remaining area of the disc excluding internal perimeter.
Here is an illustration of the sample, in which the red curve is counted but the green curve is not.
Input
The first line contains one integer T, indicating the number of test cases.
The following lines describe all the test cases. For each test case:
The first line contains two integers mm and R.
The ii-th line of the following mm lines contains three integers xi,yi and ri, indicating a cutting area.
1 ≤ T ≤ 1000, 1 ≤ m ≤ 100,−1000 ≤ xi,yi ≤ 1000,1 ≤ R,ri ≤ 1000 (i=1,2,⋯,m).
Output
For each test case, print the perimeter of the remaining area in one line. Your answer is considered correct if its absolute or relative error does not exceed 1e−6. Formally, let your answer be a and the jury's answer be b. Your answer is considered correct if (|a−b|) / (max(1, |b| ) ≤ 1e−6.
Sample Input
1
4 10
6 3 5
10 -4 3
-2 -4 4
0 9 1
Sample Output
81.62198908430238475376
二、题意:
给你一个圆心在(0,0)的大圆,及其半径R,然后给出 m 个小圆的圆心坐标及半径,求该大圆删去与小圆分割部分后的外围周长(题目保证小圆不会相交,且小圆不会完全把大圆覆盖),即图示红色曲线的总长度(绿线不算)。
三、思路:
注意:
1)求的是周长,不是面积,不是面积,不是面积,不要问我怎么知道的... 周长可比面积简单多了...
2)包含在大圆内的小圆,即图示绿线,无需计算。
3)内切需计算其周长,但外切无需计算。
4)运用扇形公式时,注意计算出的角度是弧度制还是角度制。
5)圆周率 π 可用 acos ( -1 ) 表示最为准确。
6)得到的α是圆心角的一半还是等于圆心角,若为一半则需 * 2。
思路:
首先令所求 ans = 大圆周长,然后每次根据外围长变化再加减即可。
对于每个小圆,根据给出的小圆圆心坐标求出两圆圆心距 dis ,由此可得出两圆关系:
1)包含( dis < R-r ):无需计算。
2)相离( dis > R+r ):无需计算。
3)外切( dis == R+r ):无需计算。
4)内切( dis == R-r ):直接加上小圆周长。
5)相交( R-r < dis && dis < R+r ):
h 表示的是大圆圆心到弦的距离,由大圆半径和小圆半径分别和弦构成的三角形,有共用的边,据此根据勾股定理即可列出关系:R * R - h * h = r * r - ( h - dis ) * ( h - dis ),从而解出 h 。
然后用 h 和两圆半径分别计算弧度。由扇形公式得弧长 L = R * acos α ,分别计算出大圆及小圆圆心角对应的弧长,然后加上小圆圆心角对应的弧长,再减去大圆圆心角对应的弧长即可。
相交虽然有两种情况 (dis <= h 和 dis > h ),但均可采用此种计算方法。
四、代码:
#include <cstdio>
#include <algorithm>
#define pai acos(-1)
using namespace std;
int main()
{
int T, m;
double R;
scanf("%d", &T);
while(T--)
{
scanf("%d %lf", &m, &R);
double ans = 2.0*pai*R;
double x, y, r, dis;
for(int i=0; i<=m-1; ++i)
{
scanf("%lf %lf %lf",&x, &y, &r);
dis = sqrt(x*x + y*y);
if(dis == R-r) //内切
ans += 2.0*pai*r;
else if(R-r < dis && dis < R+r) //相交
{
double h = (R*R-r*r+dis*dis)/(dis*2.0);
ans += 2.0*r*acos((dis-h)/r);
ans -= 2.0*R*acos(h/R);
}
}
printf("%.20lf\n",ans);
}
return 0 ;
}