先将所有点随机排列,然后枚举每个点,如果超出圆的范围就再枚举另外两个点求出圆心。
这样看上去是
O(n3)
的,实际上可以证明期望为
O(n)
。
求圆心可以假设出圆的方程然后解三元一次方程组。注意判断共线的情况。
#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int N=1000010;
const db Eps=1e-10;
typedef pair<db,db>abcd;
#define X first
#define Y second
int k,n,m,p;
abcd a[N];
db x,y,r;
inline db Dis(int n){
return sqrt((a[n].X-x)*(a[n].X-x)+(a[n].Y-y)*(a[n].Y-y));
}
inline db Cross(db X1,db Y1,db X2,db Y2){
return X1*Y2-X2*Y1;
}
inline db Max(db a,db b,db c){
return max(a,max(b,c));
}
inline db Min(db a,db b,db c){
return min(a,min(b,c));
}
inline db Abs(db x){
return x>0?x:-x;
}
inline void Get(db X1,db Y1,db X2,db Y2,db X3,db Y3){
if(Abs(Cross(X2-X1,Y2-Y1,X3-X2,Y3-Y2))<Eps){
x=(Max(X1,X2,X3)+Min(X1,X2,X3))/2;
y=(Max(Y1,Y2,Y3)+Min(Y1,Y2,Y3))/2;
return;
}
db A=X1*X1+Y1*Y1,B=X2*X2+Y2*Y2,C=X3*X3+Y3*Y3;
db a1=X3-X2,a2=X1-X3,a3=X1-X2;
db b1=Y3-Y2,b2=Y1-Y3,b3=Y1-Y2;
x=(b1*A+b2*B-b3*C)/(b1*X1+b2*X2-b3*X3)/2;
y=(a1*A+a2*B-a3*C)/(a1*Y1+a2*Y2-a3*Y3)/2;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].X,&a[i].Y);
random_shuffle(a+1,a+n+1);
x=a[1].X;y=a[1].Y;
for(int i=2;i<=n;i++){
if(Dis(i)>r+Eps){
x=(a[1].X+a[i].X)/2;y=(a[1].Y+a[i].Y)/2;r=Dis(i);
for(int j=2;j<i;j++)
if(Dis(j)>r+Eps){
x=(a[i].X+a[j].X)/2;y=(a[i].Y+a[j].Y)/2;r=Dis(i);
for(int k=1;k<j;k++)
if(Dis(k)>r+Eps){
Get(a[i].X,a[i].Y,a[j].X,a[j].Y,a[k].X,a[k].Y);
r=Dis(i);
}
}
}
}
printf("%.2lf %.2lf %.2lf\n",x,y,r);
return 0;
}