1336: [Balkan2002]Alien最小圆覆盖
Time Limit: 1 Sec Memory Limit: 162 MBSec Special Judge
Submit: 2017 Solved: 901
[Submit][Status][Discuss]
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
sol
最小圆覆盖裸题。我们考虑如果我们已经有了覆盖前i-1个点的最小圆,第i个点加入时,如果在圆内就不管了,否则第i个点肯定在圆的边界上。那么我们就从以第1和i个点作为边界随便构个圆,再去找2->i-1中不在圆内的点j,同理j也在新圆的边界上,再去找k,3个点就能确定一个圆。我是抄了份代码然后这样感性理解的,至于为什么这3个点能包括1->i的所有点我还是有点搞不明白。
很玄妙的是这题只输出2位小数会错。
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
typedef double s64;
int n;
const int N=110000;
struct P
{
s64 x,y;
friend inline P operator -(const P &a,const P &b)
{
return (P){a.x-b.x,a.y-b.y};
}
friend inline P operator +(const P &a,const P &b)
{
return (P){b.x+a.x,b.y+a.y};
}
friend inline s64 operator *(const P &a,const P &b)
{
return a.x*b.y-a.y*b.x;
}
friend inline P operator *(const P &a,s64 b)
{
return (P){a.x*b,a.y*b};
}
friend inline s64 operator /(const P &a,const P &b)
{
return b.x*a.x+b.y*a.y;
}
}a[N];
inline P rev(const P &a)
{
return (P){-a.y,a.x};
}
struct L
{
P a,b,v;
friend inline P inter(const L &a,const L &b)
{
P nw=b.a-a.a;
s64 tt=(nw*a.v)/(a.v*b.v);
return b.a+b.v*tt;
}
};
const s64 eps=1e-7;
inline s64 sqr(const s64 &x)
{
return x*x;
}
inline s64 dis(const P &a,const P &b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
inline P find(P a,P b,P c)
{
if(fabs((b-a)*(c-b))<=eps)
{
if(b.x>c.x) swap(b,c);
if(a.x>b.x) swap(a,b);
if(b.x>c.x) swap(b,c);
return (a+c)*0.5;
}
L x,y;
x.a=(a+b)*0.5;
x.v=rev(b-a);
x.b=x.a+x.v;
y.a=(b+c)*0.5;
y.v=rev(c-b);
y.b=y.a+y.v;
return inter(x,y);
}
int main()
{
// freopen("1336.in","r",stdin);
// freopen("1336.out","w",stdout);
cin>>n;
for(int i=1;i<=n;++i)
scanf("%lf%lf",&a[i].x,&a[i].y);
srand(19260817);
random_shuffle(a+1,a+1+n);
P t; s64 r;
t=a[1];r=0.0;
for(int i=2;i<=n;++i)
if(dis(t,a[i])>r+eps)
{
t=(a[1]+a[i])*0.5;
r=dis(a[1],t);
for(int j=2;j<i;++j)
if(dis(t,a[j])>r+eps)
{
t=(a[i]+a[j])*0.5;
r=dis(a[i],t);
for(int k=1;k<j;++k)
if(dis(t,a[k])>r+eps)
{
t=find(a[i],a[j],a[k]);
r=dis(t,a[i]);
}
}
}
printf("%.2lf\n%.2lf %.2lf",r,t.x,t.y);
}