1 /*UVA 10969计算几何 2 这道题和LA2572相似,但相对简单些。 3 思路:求圆间的交点,顺序枚举出圆上的圆弧,中点判断是否被覆盖。 4 */ 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <math.h> 9 #include <ctype.h> 10 #include <string> 11 #include <iostream> 12 #include <sstream> 13 #include <vector> 14 #include <queue> 15 #include <stack> 16 #include <map> 17 #include <list> 18 #include <set> 19 #include <algorithm> 20 #define INF 0x3f3f3f3f 21 #define eps 1e-7 22 #define eps2 1e-3 23 using namespace std; 24 25 struct Point 26 { 27 double x,y; 28 Point() {} 29 Point(double xx,double yy) 30 { 31 x=xx; 32 y=yy; 33 } 34 }; 35 struct Circle 36 { 37 Point O; 38 double r; 39 Circle() {} 40 Circle(Point O1,double r1) 41 { 42 O=O1; 43 r=r1; 44 } 45 Point point(double a) 46 { 47 return Point(O.x+cos(a)*r,O.y+sin(a)*r); 48 } 49 }; 50 typedef Point Vector; 51 52 bool operator==(Point A,Point B) 53 { 54 if ((fabs(A.x-B.x)<1e-10) && (fabs(A.y-B.y)<1e-10)) return true; 55 else return false; 56 } 57 Vector operator-(Point A,Point B)//表示A指向B 58 { 59 return Vector(A.x-B.x,A.y-B.y); 60 } 61 Vector operator*(Vector A,double k) 62 { 63 return Vector(A.x*k,A.y*k); 64 } 65 Vector operator+(Point A,Point B)//表示A指向B 66 { 67 return Vector(B.x+A.x,B.y+A.y); 68 } 69 double Dot(Vector A,Vector B) 70 { 71 return A.x*B.x+A.y*B.y; 72 } 73 double Length(Vector A) 74 { 75 return sqrt(Dot(A,A)); 76 } 77 double Cross(Vector A,Vector B) 78 { 79 return A.x*B.y-A.y*B.x; 80 } 81 int dcmp(double x) 82 { 83 if(fabs(x)<1e-10) return 0; 84 else if(x>0) return 1; 85 else return -1; 86 } 87 double angle(Vector v) 88 { 89 return atan2(v.y,v.x); 90 } 91 double normal(double rad) 92 { 93 return rad-2*M_PI*floor(rad/(2*M_PI)); 94 } 95 96 Point GetMid(double a,double b,double r,double x,double y)//圆上两点,获得中点的坐标 97 { 98 double arf=(b+a)/2; 99 double xx=r*cos(arf)+x; 100 double xy=r*sin(arf)+y; 101 Point P=Point(xx,xy); 102 return P; 103 } 104 bool PInCircle(Point P,Circle C)//判断点在圆内 105 { 106 double dis=Length(P-C.O); 107 if (dis-C.r>1e-6) return false; 108 else return true; 109 } 110 void getcircleinter(Point c1,double r1,Point c2,double r2,vector<double>& rad) 111 { 112 double d=Length(c1-c2); 113 if(dcmp(d)==0) return; 114 if(dcmp(r1+r2-d)<0) return; 115 if(dcmp(fabs(r1-r2)-d)>0) return; 116 double a=angle(c2-c1); 117 double da=acos((r1*r1+d*d-r2*r2)/(2*r1*d)); 118 rad.push_back(normal(a+da)); 119 rad.push_back(normal(a-da)); 120 } 121 122 int n; 123 Circle CC[110];//圆 124 vector<double> Arf[110];//圆心角 125 126 int cas; 127 int main() 128 { 129 cin>>cas; 130 while(cas--) 131 { 132 double ans=0.0; 133 cin>>n; 134 for(int i=1; i<=n; i++)//读取信息 135 { 136 double x,y,r; 137 cin>>r>>x>>y; 138 CC[i]=Circle(Point(x,y),r); 139 } 140 for(int i=1; i<=n; i++) {Arf[i].clear();Arf[i].push_back(0);Arf[i].push_back(2*M_PI);} 141 142 for(int i=1; i<=n; i++)//获得圆上的交点的角度 143 for(int j=1; j<=n; j++) 144 getcircleinter(CC[i].O,CC[i].r,CC[j].O,CC[j].r,Arf[i]); 145 146 for(int i=1; i<=n; i++) //枚举n个圆上的圆弧 147 { 148 int k=Arf[i].size(); 149 sort(Arf[i].begin(),Arf[i].end()); 150 151 for(int j=0; j<k-1; j++) //枚举每条弧 152 { 153 Point Mid=GetMid(Arf[i][j],Arf[i][j+1],CC[i].r,CC[i].O.x,CC[i].O.y); 154 155 bool ok=true;//表示这条圆弧可见 156 for(int l=i+1; l<=n; l++) //判断中点是否可见 157 if (PInCircle(Mid,CC[l])) ok=false; 158 159 if(ok) ans+=(Arf[i][j+1]-Arf[i][j])*CC[i].r; 160 } 161 } 162 163 printf("%.3lf ",(ans));//放缩回来 164 } 165 return 0; 166 }