其他分享
首页 > 其他分享> > 【计算几何】最小圆覆盖

【计算几何】最小圆覆盖

作者:互联网

期望复杂度 \(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);
}

标签:覆盖,Point,int,double,最小,cc,distTo,几何,Circle
来源: https://www.cnblogs.com/purinliang/p/14497687.html