题意
简单说一下做法,并不知道怎么证明:
假设当前求出了([1,i-1])的最小覆盖圆,现在考虑([1,i])的最小覆盖圆:
如果(i)在当前圆中就不必改动。
不然(i)必定在圆上,我们令圆心为(i),半径为(0)。
现在固定了一个点,我们枚举(jin[1,i-1]),如果(j)不在当前圆中,我们固定(j)。
现在固定了两个点,我们枚举(kin[1,j-1]),如果(k)不在当前圆中,就固定(k),现在固定了三个点,可以求出圆。
复杂度:期望(O(n))很假的样子,但就是真的。
固定三个点求圆:从两条弦做中垂线求交点便是圆心。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
const double eps=1e-12;
const double Pi=acos(-1.0);
int n;
struct Point
{
double x,y;
inline double len(){return x*x+y*y;}
Point operator+(const Point a)const{return (Point){x+a.x,y+a.y};}
Point operator-(const Point a)const{return (Point){x-a.x,y-a.y};}
Point operator*(const double k){return (Point){x*k,y*k};}
Point operator/(const double k){return (Point){x/k,y/k};}
double operator*(const Point a)const{return x*a.y-y*a.x;}
double operator&(const Point a)const{return x*a.x+y*a.y;}
}p[maxn];
inline int dcmp(double x)
{
if(fabs(x)<=eps)return 0;
return x<0?-1:1;
}
struct Line{Point p,v;};
inline Point turn(Point a,double theta)
{
return (Point){a.x*cos(theta)-a.y*sin(theta),a.x*sin(theta)+a.y*cos(theta)};
}
inline Point get(Point a,Point b){return b-a;}
inline Point getpoint(Line a,Line b)
{
Point p1=a.p,p2=b.p,v1=a.v,v2=b.v;
Point u=get(p1,p2);
Point res=p1+v1*((u*v2)/(v1*v2));
return res;
}
inline Point find_circle(Point a,Point b,Point c)
{
return getpoint((Line){(a+b)/2.0,turn(get(a,b),Pi/2.0)},(Line){(a+c)/2.0,turn(get(a,c),Pi/2.0)});
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
random_shuffle(p+1,p+n+1);
Point now=(Point){0,0};double nowr=0;
for(int i=1;i<=n;i++)
{
if(dcmp(get(now,p[i]).len()-nowr)<=0)continue;
now=p[i],nowr=0;
for(int j=1;j<i;j++)
{
if(dcmp(get(now,p[j]).len()-nowr)<=0)continue;
now=(p[i]+p[j])/2.0;nowr=get(now,p[j]).len();
for(int k=1;k<j;k++)
{
if(dcmp(get(now,p[k]).len()-nowr)<=0)continue;
now=find_circle(p[i],p[j],p[k]);nowr=get(now,p[k]).len();
}
}
}
printf("%.10lf
%.10lf %.10lf",sqrt(nowr),now.x,now.y);
return 0;
}