[BZOJ2823][BZOJ1336][BZOJ1337]最小圆覆盖(随机增量法)
算法介绍网上有很多,不解释了。
给出三点坐标求圆心方法:https://blog.csdn.net/liyuanbhu/article/details/52891868
记得先random_shuffle()一下。
1 #include<cmath> 2 #include<cstdio> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 using namespace std; 6 7 const int N=100010; 8 const double eps=1e-8; 9 int n; 10 double r; 11 struct P{ double x,y; }a[N],c; 12 13 double sqr(double x){ return x*x; } 14 double dis(P a,P b){ return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); } 15 16 P get(P &A,P &B,P &C){ 17 double a=A.x-B.x,b=A.y-B.y,c=A.x-C.x,d=A.y-C.y; 18 double e=((sqr(A.x)-sqr(B.x))-(sqr(B.y)-sqr(A.y)))/2; 19 double f=((sqr(A.x)-sqr(C.x))-(sqr(C.y)-sqr(A.y)))/2; 20 return (P){(d*e-b*f)/(a*d-b*c),(a*f-c*e)/(a*d-b*c)}; 21 } 22 23 void work(){ 24 random_shuffle(a+1,a+n+1); 25 r=0; c=a[1]; 26 rep(i,2,n) if (dis(c,a[i])>r+eps){ 27 c=a[i]; r=0; 28 rep(j,1,i-1) if (dis(a[j],c)>r+eps){ 29 c=(P){(a[i].x+a[j].x)/2,(a[i].y+a[j].y)/2}; r=dis(c,a[i]); 30 rep(k,1,j-1) if (dis(a[k],c)>r+eps){ 31 c=get(a[i],a[j],a[k]); r=dis(c,a[i]); 32 } 33 } 34 } 35 } 36 37 int main(){ 38 scanf("%d",&n); 39 rep(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y); 40 work(); printf("%lf\n%lf %lf\n",r,c.x,c.y); 41 return 0; 42 }