【计算几何】最小圆覆盖
期望复杂度 \(O(n)\)
const double PI = acos(-1.0);
const double EPS = 1e-10;
double sqr(double x) {
return x * x;
}
struct Point {
double x, y;
};
struct Circle {
double x, y, r;
double distTo(Point a) {
return sqrt(sqr(x - a.x) + sqr(y - a.y));
}
};
Circle getCircleFromTriangle(Point &a, Point &b, Point &c) {
double A1 = a.x - b.x, B1 = a.y - b.y;
double A2 = c.x - b.x, B2 = c.y - b.y;
double C1 = (a.x * a.x - b.x * b.x + a.y * a.y - b.y * b.y) / 2;
double C2 = (c.x * c.x - b.x * b.x + c.y * c.y - b.y * b.y) / 2;
Circle cc;
cc.x = (C1 * B2 - C2 * B1) / (A1 * B2 - A2 * B1);
cc.y = (A1 * C2 - A2 * C1) / (A1 * B2 - A2 * B1);
cc.r = cc.distTo(a);
return cc;
}
Circle getMinCoverCircle(Point p[], int n) {
srand(time(0));
random_shuffle(p + 1, p + 1 + n);
Circle c;
c.x = p[1].x; c.y = p[1].y; c.r = 0;
for (int i = 2; i <= n; ++i) {
if (c.distTo(p[i]) >= c.r + EPS) {
c.x = p[i].x, c.y = p[i].y, c.r = 0;
for (int j = 1; j < i; ++j)
if (c.distTo(p[j]) >= c.r + EPS) {
c.x = (p[i].x + p[j].x) / 2;
c.y = (p[i].y + p[j].y) / 2;
c.r = c.distTo(p[i]);
for (int k = 1; k < j; ++k)
if (c.distTo(p[k]) >= c.r + EPS)
c = getCircleFromTriangle(p[i], p[j], p[k]);
}
}
}
return c;
}
const int MAXN = 1e5 + 10;
int n;
Point p[MAXN];
void solve() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%lf%lf", &p[i].x, &p[i].y);
Circle c = getMinCoverCircle(p, n);
printf("%.8f\n%.8f %.8f\n", c.r, c.x, c.y);
}