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");

posted @ 2019-01-28 11:42  蒟蒻--lichenxi  阅读(81)  评论(0编辑  收藏  举报