首页 > 技术文章 > 【计算几何】平面最近点对

purinliang 2021-03-09 15:10 原文

复杂度确定的分治算法(还带有一个最优性剪枝)

const int MAXN = 2e5 + 10;
const double MAXDIS = 1e20;

int n;
struct Point {
    double x, y;
} p[MAXN];

double calc(int l, int r, double res) {
    static auto dis = [](int i, int j) {
        double x = (p[i].x - p[j].x) * (p[i].x - p[j].x);
        double y = (p[i].y - p[j].y) * (p[i].y - p[j].y);
        return sqrt(x + y);
    };
    if (r - l + 1 <= 4) {
        for (int i = l; i <= r; ++i) {
            for (int j = i + 1; j <= r; ++j)
                res = min(res, dis(i, j));
        }
        return res;
    }
    static int tmp[MAXN];
    int mid = (l + r) / 2, top = 0;
    res = min(res, calc(l, mid, res));
    res = min(res, calc(mid + 1, r, res));
    for (int i = l; i <= r; ++i) {
        if (abs(p[mid].x - p[i].x) < res)
            tmp[++top] = i;
    }
    sort(tmp + 1, tmp + 1 + top, [](const int &a, const int &b) {
        return p[a].y < p[b].y;
    });
    for (int i = 1; i <= top; ++i) {
        for (int j = i + 1; j <= top; ++j) {
            if (p[tmp[j]].y - p[tmp[i]].y >= res)
                break;
            res = min(res, dis(tmp[i], tmp[j]));
        }
    }
    return res;
}

double getClosestDistance(int n) {
    sort(p + 1, p + 1 + n, [](const Point & a, const Point & b) {
        return (a.x != b.x) ? a.x < b.x : a.y < b.y;
    });
    return calc(1, n, MAXDIS);
}

void solve() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%lf%lf", &p[i].x, &p[i].y);
    printf("%.12f\n", getClosestDistance(n));
    return;
}

练习

https://codeforces.com/contest/120/problem/J

推荐阅读