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 阅读(37) 评论(0) 收藏 举报