【Balkan2002】【BZOJ1336】Alien最小圆覆盖

来源:互联网 发布:网络正常守望先锋卡 编辑:程序博客网 时间:2024/05/16 14:12

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 100100using 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);}
0 0