Description
给出平面上N个点,N<=10^5.请求出一个半径最小的圆覆盖住所有的点。
这道题先对点随机化处理,设前个点的最小圆覆盖为,若当前要加入的点不在内则一定在的边界上,然后在~中枚举,若不在圆内,就以为直径构成圆,再在1~中枚举,用三点构成新圆即可,下面是程序(注意三题的输出格式不同):
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<iostream>
using namespace std;
const int N=100005;
const double eps=1e-10;
struct Point{
double x,y;
Point operator +(const Point &p)const{
return (Point){x+p.x,y+p.y};
}
Point operator /(const double p)const{
return (Point){x/p,y/p};
}
}p[N],o,t1,t2;
int n;
double r;
double L(Point &a,Point &b){
double x=a.x-b.x,y=a.y-b.y;
return x*x+y*y;
}
void makec(Point &a,Point &b,Point &c){
double a1,a2,b1,b2,c1,c2;
a1=2*(b.x-a.x);
b1=2*(b.y-a.y);
c1=(b.x+a.x)*(b.x-a.x)+(b.y+a.y)*(b.y-a.y);
a2=2*(c.x-b.x);
b2=2*(c.y-b.y);
c2=(c.x+b.x)*(c.x-b.x)+(c.y+b.y)*(c.y-b.y);
o.x=(c1*b2-c2*b1)/(a1*b2-a2*b1);
o.y=(a1*c2-a2*c1)/(a1*b2-a2*b1);
r=L(o,a);
}
inline bool in(Point &p){
return r-L(p,o)>=-eps;
}
int main(){
srand(9837528);
int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
random_shuffle(p+1,p+n+1);
makec(p[1],p[2],p[3]);
for(i=4;i<=n;i++){
if(in(p[i])){
continue;
}
o=p[i],r=0;
for(j=1;j<i;j++){
if(in(p[j])){
continue;
}
o=(p[i]+p[j])/2;
r=L(p[i],o);
for(k=1;k<j;k++){
if(in(p[k])){
continue;
}
makec(p[i],p[j],p[k]);
}
}
}
printf("%.10lf\n%.10lf %.10lf",sqrt(r),o.x,o.y);
return 0;
}