[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 }

 

posted @ 2018-07-15 11:02  HocRiser  阅读(290)  评论(0编辑  收藏  举报