Description
给出N个点,让你画一个最小的包含所有点的圆。
Input
先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0)
Output
输出圆的半径,及圆心的坐标
Sample Input
6
8.0 9.0
4.0 7.5
1.0 2.0
5.1 8.7
9.0 2.0
4.5 1.0
Sample Output
5.00
5.00 5.00
HINT
Source
跟AHOI2012信号塔是一样的
但是
eps开到1e-12
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<ctime>
#define eps 1e-12
#define MAXN 100100
using namespace std;
int n;
double r;
struct point
{
double x,y;
}s[MAXN],C;
double sqr(double x)
{
return x*x;
}
double dis(point a,point b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
point cen(point a,point b,point c)//已知三点求圆心
{
double x,y;
double ax=sqr(a.x),ay=sqr(a.y),bx=sqr(b.x),by=sqr(b.y),cx=sqr(c.x),cy=sqr(c.y);
double l1=ax-bx+ay-by,l2=ax-cx+ay-cy;
double r1=2*a.x-2*b.x,r2=2*a.y-2*b.y,r3=2*a.x-2*c.x,r4=2*a.y-2*c.y;
x=(l1-r2/r4*l2)/(r1-r2/r4*r3);y=(l1-r1/r3*l2)/(r2-r1/r3*r4);
if (r4==0) x=(a.x+c.x)/2;
if (r3==0) y=(a.y+c.y)/2;
return (point){x,y};
}
point Mid(point a,point b)
{
return (point){(a.x+b.x)/2,(a.y+b.y)/2};
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&s[i].x,&s[i].y);
swap(s[i],s[rand()%i+1]);
}
C=s[1];
for (int i=1;i<=n;i++)
{
if (dis(C,s[i])<=r+eps) continue;
C=Mid(s[1],s[i]);r=dis(s[i],C);
for (int j=1;j<i;j++)
{
if (dis(C,s[j])<=r+eps) continue;
C=Mid(s[i],s[j]);r=dis(s[i],C);
for (int k=1;k<j;k++)
{
if (dis(C,s[k])<=r+eps) continue;
C=cen(s[i],s[j],s[k]);r=dis(s[i],C);
}
}
}
printf("%.6lf\n%.6lf %.6lf",r,C.x,C.y);
}