///给你若干个没有交集的圆,以其中一个圆的圆心为圆心做一个圆 ///使得这个圆至少包含所有圆面积的一半,求这个圆最小的半径 # include <stdio.h> # include <algorithm> # include <iostream> # include <string.h> # include <math.h> #include <string> using namespace std; struct node { double x; double y; double r; }; int t1,t2; double rr; const double d = 1e-10; const double pi = acos(-1.0); struct node a[25]; double ss; double cal(int x1,int y1)///两圆圆心距离 { return sqrt((a[x1].x-a[y1].x)*(a[x1].x-a[y1].x)*1.0+(a[x1].y-a[y1].y)*(a[x1].y-a[y1].y)*1.0); } double area(double mid)///求两圆交叉面积 { double a = cal(t1, t2), b = rr, c = mid; double cta1 = acos((a * a + b * b - c * c) / 2 / (a * b)), cta2 = acos((a * a + c * c - b * b) / 2 / (a * c)); double s1 = rr*rr*cta1 - rr*rr*sin(cta1)*(a * a + b * b - c * c) / 2 / (a * b); double s2 = mid*mid*cta2 - mid*mid*sin(cta2)*(a * a + c * c - b * b) / 2 / (a * c); return s1 + s2; } double f(double m) { if(area(m)-ss>=1e-20) return 1; else return 0; } int main() { int t,n,i,j; double min1,max1,min2,max2,jj; while(~scanf("%d",&t)) { while(t--) { scanf("%d",&n); for(i=0; i<n; i++) scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r); if(n==1) { min1=sqrt(a[0].r*a[0].r*0.5); printf("%.4lf\n",min1); } else { double lll=1000000000; for(i=0; i<n; i++) { max1=-1; double ll=-1; for(j=0; j<n; j++) { if(i!=j) { t2=i; t1=j; rr=a[t1].r; max1=cal(i,j); min2=max1+rr; ss=pi*rr*rr*0.5; double l=max1; double r=min2; while(r-l>d)///二分面积 { double mid=(l+r)/2; if(f(mid)==1) r=mid; else l=mid; } ll=max(ll,l); } } lll=min(lll,ll); } printf("%.4lf\n",lll); } } } return 0; }
原文:http://blog.csdn.net/lp_opai/article/details/41050913