枚举伞的圆心,最多只有20个,因为必须与某个现有的圆心重合。
然后再二分半径就可以了。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 25 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 struct point 18 { 19 double x,y; 20 double r,s; 21 point(double x=0,double y=0):x(x),y(y) {} 22 } p[N]; 23 int n; 24 typedef point pointt; 25 pointt operator -(point a,point b) 26 { 27 return point(a.x-b.x,a.y-b.y); 28 } 29 int dcmp(double x) 30 { 31 if(fabs(x)<eps) return 0; 32 return x<0?-1:1; 33 } 34 double circle_area(point a,point b) 35 { 36 double s,d,t,t1; 37 d=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 38 if(d>=a.r+b.r) s=0; 39 else if(d<=fabs(a.r-b.r)) s=min(acos(-1.0)*a.r*a.r,acos(-1.0)*b.r*b.r); 40 else 41 { 42 t=(a.r*a.r+d*d-b.r*b.r)/2.0/d; 43 t1=sqrt(a.r*a.r-t*t); 44 s=-d*t1+a.r*a.r*acos(t/a.r)+b.r*b.r*acos((d-t)/b.r); 45 } 46 return s; 47 } 48 int cal(double mid,point pp) 49 { 50 int i; 51 double sum; 52 pp.r = mid; 53 for(i = 1 ; i <= n ; i++) 54 { 55 sum = circle_area(pp,p[i]); 56 if(dcmp(sum-p[i].s/2)<0) return 0; 57 } 58 //cout<<mid<<" "<<pp.x<<" "<<pp.y<<" "<<pp.r<<endl; 59 return 1; 60 } 61 double solve(point pp) 62 { 63 double rig = 20001,lef = 0,mid; 64 while(rig-lef>eps) 65 { 66 mid = (rig+lef)/2; 67 if(cal(mid,pp)) 68 rig = mid; 69 else lef = mid; 70 } 71 return rig; 72 } 73 int main() 74 { 75 int t,i; 76 cin>>t; 77 while(t--) 78 { 79 scanf("%d",&n); 80 for(i = 1; i <= n ; i++) 81 { 82 scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].r); 83 p[i].s = pi*p[i].r*p[i].r; 84 } 85 double ans = INF; 86 for(i = 1; i <= n ; i++) 87 { 88 ans = min(ans,solve(p[i])); 89 } 90 printf("%.4f ",ans); 91 } 92 return 0; 93 }