给定一些点,求一个圆,可以覆盖所有这些点。
随机增量,每次找一个不在当前圆内的点,将圆调整扩大至该点在圆周上,期望复杂度为O(n)。
调用之前应把点打乱顺序。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
int mx,my,n;
const int maxn = 1e4 + 5;
const double eps = 1e-8;
struct point{
double x,y;
point(double x= 0,double y = 0):x(x),y(y){}
double dist(){return sqrt(x * x + y * y);}
}p[maxn];
point operator - (const point &a,const point &b){
return point(a.x - b.x,a.y - b.y);
}
int dcmp(double x){
return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);
}
void circle_center(point p0,point p1,point p2,point &cp){
double a1 = p1.x - p0.x,b1 = p1.y - p0.y,c1 = (a1 * a1 + b1 * b1) / 2;
double a2 = p2.x - p0.x,b2 = p2.y - p0.y,c2 = (a2 * a2 + b2 * b2) / 2;
double d = a1 * b2 - a2 * b1;
cp.x = p0.x + (c1 * b2 - c2 * b1) / d;
cp.y = p0.y + (a1 * c2 - a2 * c1) / d;
}
void circle_center(point p0,point p1,point &cp){
cp.x = (p0.x + p1.x) / 2;
cp.y = (p0.y + p1.y) / 2;
}
point center;
double radius;
bool point_in(const point &p){
return dcmp((p - center).dist() - radius) < 0;
}
void min_circle_cover(point a[],int n){
radius = 0;
center = p[0];
for (int i = 1; i< n; i ++) {
if(!point_in(a[i])){
center = a[i];radius = 0;
for (int j = 0; j < i; j ++) {
if(!point_in(a[j])){
circle_center(a[i], a[j], center);
radius = (a[j] - center).dist();
for (int k = 0; k < j; k ++) {
if(!point_in(a[k])){
circle_center(a[i], a[j], a[k], center);
radius = (a[k] - center).dist();
}
}
}
}
}
}
}
int main()
{
srand(unsigned(time(0)));
while (scanf("%d%d%d",&mx,&my,&n) != EOF) {
for (int i = 0; i < n; i ++) {
scanf("%lf%lf",&p[i].x,&p[i].y);
}
random_shuffle(p, p + n);//随机排列数组
min_circle_cover(p, n);
printf("(%.1lf,%.1lf).\n",center.x,center.y);
printf("%.1lf\n",radius);
}
return 0;
}