题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6354
题目:
题意:用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长(图中的红线部分)。
思路:首先判定圆与圆A的关系,这题我们只需要与A内切、相交的圆。然后就是求每个圆把圆A切割掉多少周长,增加了多少周长(因为圆A被切割的部分在切割后绝对是内凹的,此时周长是增加的),内切的时候直接加上切割圆的周长(如最上面的那个小圆),相交的圆部分我采用的方法是用余弦定理(A的半径记为R,切割圆半径为r,二者的圆心距离为d,圆心的连线与 圆A和一个交点的夹角为a,则2*d*R*cosa=R*R+d*d-r*r)求出夹角a,再用弧长公式l=a*r求出弧长最后进行加减即可。
代码实现如下:
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <bitset> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 typedef long long ll; 17 typedef pair<ll, ll> pll; 18 typedef pair<ll, int> pli; 19 typedef pair<int, ll> pil;; 20 typedef pair<int, int> pii; 21 typedef unsigned long long ull; 22 23 #define lson i<<1 24 #define rson i<<1|1 25 #define bug printf("*********\n"); 26 #define FIN freopen("D://code//in.txt", "r", stdin); 27 #define debug(x) cout<<"["<<x<<"]" <<endl; 28 #define IO ios::sync_with_stdio(false),cin.tie(0); 29 30 const double eps = 1e-8; 31 const int mod = 10007; 32 const int maxn = 1e6 + 7; 33 const double pi = acos(-1); 34 const int inf = 0x3f3f3f3f; 35 const ll INF = 0x3f3f3f3f3f3f3f; 36 37 typedef struct stu { 38 double x,y; 39 } point; 40 41 double Distance(point a,point b) { 42 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 43 } 44 45 double Inter(point a,double R,point b,double r) { //变化的周长 46 double dis=Distance(a,b); 47 double angle1=acos((R*R+dis*dis-r*r)/(2.0*R*dis)); 48 double angle2=acos((r*r+dis*dis-R*R)/(2.0*r*dis)); 49 double s=r*angle2*2-R*angle1*2; 50 return s; 51 } 52 53 int t, m, R; 54 double x, y, r, ans; 55 stu o, p; 56 57 int main() { 58 //FIN; 59 scanf("%d", &t); 60 while(t--) { 61 scanf("%d%d", &m, &R); 62 ans = 2 * pi * R; 63 o.x = 0, o.y = 0; 64 for(int i = 1; i <= m; i++) { 65 scanf("%lf%lf%lf", &x, &y, &r); 66 p.x = x, p.y = y; 67 double d = Distance(o, p); 68 if(d - R - r >= eps) continue; //外离 69 if(fabs(R - r) - d > eps) continue; //内离 70 if(R == r + d) { //内切 71 ans += 2 * pi * r; 72 } else { //相交 73 ans += Inter(o, R, p, r); 74 } 75 } 76 printf("%.12f\n", ans); 77 } 78 return 0; 79 }