1337: 最小圆覆盖
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 939 Solved: 463
[ Submit][ Status][ Discuss]
Description
给出平面上N个点,N<=10^5.请求出一个半径最小的圆覆盖住所有的点
Input
第一行给出数字N,现在N行,每行两个实数x,y表示其坐标.
Output
输出最小半径,输出保留三位小数.
Sample Input
4
1 0
0 1
0 -1
-1 0
1 0
0 1
0 -1
-1 0
Sample Output
1.000
HINT
Source
题解:随机增量法求最小圆覆盖
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 100005
#define eps 1e-7
using namespace std;
int n,m;
struct vector {
double x,y;
vector (double X=0,double Y=0){
x=X,y=Y;
}
}p[N],tmp;
double x,y,ans,r,pi=acos(-1.0);
typedef vector point;
vector operator -(vector a,vector b){
return vector (a.x-b.x,a.y-b.y);
}
vector operator +(vector a,vector b){
return vector (a.x+b.x,a.y+b.y);
}
vector operator *(vector a,double t){
return vector (a.x*t,a.y*t);
}
vector operator /(vector a,double t){
return vector (a.x/t,a.y/t);
}
int dcmp(double x)
{
if (fabs(x)<eps) return 0;
return x<0?-1:1;
}
double len(vector a)
{
return sqrt(a.x*a.x+a.y*a.y);
}
double cross(vector a,vector b)
{
return a.x*b.y-a.y*b.x;
}
point glt(point a,vector v,point b,vector w)
{
vector u=a-b;
double t=cross(w,u)/cross(v,w);
return a+v*t;
}
vector rotate(vector a,double rad)
{
return vector (a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
point center(point a,point b,point c)
{
point p=(a+b)/2; point q=(a+c)/2;
vector v=rotate(b-a,pi/2); vector u=rotate(c-a,pi/2);
if (dcmp(cross(v,u))==0) {
if (dcmp(len(a-b)+len(c-b)-len(a-c))==0) return (a+c)/2;
if (dcmp(len(a-c)+len(c-b)-len(a-b))==0) return (a+b)/2;
if (dcmp(len(c-a)+len(a-b)-len(c-b))==0) return (b+c)/2;
}
return glt(p,v,q,u);
}
double mincc()
{
random_shuffle(p,p+n);
double r=0;
point c=p[0];
for (int i=1;i<n;i++)
if (dcmp(len(p[i]-c)-r)>0){
c=p[i]; r=0;
for (int j=0;j<i;j++)
if (dcmp(len(p[j]-c)-r)>0) {
c=(p[i]+p[j])/2;
r=len(c-p[i]);
for (int k=0;k<j;k++)
if (dcmp(len(p[k]-c)-r)>0) {
c=center(p[i],p[j],p[k]);
r=len(p[i]-c);
}
}
}
return r;
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d",&n);
for (int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
printf("%.3lf\n",mincc());
}