bzoj1336[Balkan2002]Alien最小圆覆盖
传送门
期望\(O(n)\)的神奇算法
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
void read(int &x){
char ch; bool ok;
for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=1e5+1;
double eps=1e-6;
int n;
struct oo{double x,y;}a[maxn];
struct circle{double x,y,r;}c;
double dis(double x,double y,oo a){return sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y));}
circle make_2(oo a,oo b){return (circle){(a.x+b.x)/2.0,(a.y+b.y)/2.0,dis((a.x+b.x)/2.0,(a.y+b.y)/2.0,b)};}
circle make_3(oo x1,oo x2,oo x3)
{
double a=x1.x-x2.x,b=x1.y-x2.y,c=x1.x-x3.x,d=x1.y-x3.y,
e=((x1.x*x1.x-x2.x*x2.x)-(x2.y*x2.y-x1.y*x1.y))/2.0,
f=((x1.x*x1.x-x3.x*x3.x)-(x3.y*x3.y-x1.y*x1.y))/2.0,x0,y0;
x0=(d*e-b*f)/(a*d-b*c),y0=(c*e-a*f)/(b*c-a*d);
return (circle){x0,y0,dis(x0,y0,x1)};
}
int main()
{
srand(1e9+7);
read(n);
for(rg int i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
random_shuffle(a+1,a+n+1);
c=make_2(a[1],a[2]);
for(rg int i=3;i<=n;i++)
if(dis(c.x,c.y,a[i])-c.r>eps)
{
c=make_2(a[1],a[i]);
for(rg int j=1;j<i;j++)
if(dis(c.x,c.y,a[j])-c.r>eps)
{
c=make_2(a[i],a[j]);
for(rg int k=1;k<j;k++)
if(dis(c.x,c.y,a[k])-c.r>eps)
c=make_3(a[i],a[j],a[k]);
}
}
printf("%lf\n%lf %lf\n",c.r,c.x,c.y);
}
或者也可以选择put("nan");