DestinHistoire

 

BZOJ-1336 [Balkan2002]Alien最小圆覆盖(最小圆覆盖模板)

题目描述

  给出 \(n(2\leq n\leq 10^5)\) 个点,求能包含所有点的半径最小的圆。

分析

  随机增量法。

代码

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-12;
struct Point
{
	double x,y;
}p[100010],O;
int n;
double r;
double Distance(Point p1,Point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
void circum(Point A,Point B,Point C)
{
	double a=B.y-A.y,b=C.y-A.y,
		   c=B.x-A.x,d=C.x-A.x,
		   e=B.x*B.x+B.y*B.y-A.x*A.x-A.y*A.y,
		   f=C.x*C.x+C.y*C.y-A.x*A.x-A.y*A.y;
	O.x=(a*f-b*e)/(2*a*d-2*b*c);
	O.y=(d*e-c*f)/(2*a*d-2*b*c); 
	r=Distance(A,O); 
} 
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+1+n);
	O=p[1];r=0;
	for(int i=2;i<=n;i++)
	{
		if(Distance(O,p[i])>r+eps)
		{
			O=p[i],r=0;
			for(int j=1;j<=i-1;j++)
			{
				if(Distance(O,p[j])>r+eps)
				{
					O.x=(p[i].x+p[j].x)/2;
					O.y=(p[i].y+p[j].y)/2;
					r=Distance(O,p[j]);
					for(int k=1;k<=j-1;k++)
						if(Distance(O,p[k])>r+eps)
							circum(p[i],p[j],p[k]);
				}
			}
		}
	}
	printf("%.10lf\n",r);
	printf("%.10lf %.10lf",O.x,O.y);
	return 0;
}

posted on 2020-11-27 18:37  DestinHistoire  阅读(33)  评论(0编辑  收藏  举报

导航