[P1427] 平面最近点对加强版 - 分治

Posted mollnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[P1427] 平面最近点对加强版 - 分治相关的知识,希望对你有一定的参考价值。

暴力沿着 (x) 轴方向分治,每次合并时,利用当前已有 (ans),只保留 ((mid-ans,mid+ans)) 内的点,将它们按 (y) 排序,对每个点找它上面 (ans) 内的点,只枚举这范围内的点对来计算答案即可

#include <bits/stdc++.h>
using namespace std;

const int N = 1000005;
const double inf = 1e18;

struct point {
    double x,y;
    bool operator < (const point &b) {
        if(x!=b.x) return x<b.x;
        else return y<b.y;
    }
} p[N];

bool cmp(const point &a, const point &b) {
    return a.y < b.y;
}

double dist2(point a,point b) {
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

int n;

double solve(int l,int r) {
    if(l==r) {
        return inf;
    }
    else {
        int mid=(l+r)/2;
        double pos=p[mid].x;
        double ans=inf;
        ans=min(ans,solve(l,mid));
        ans=min(ans,solve(mid+1,r));
        int pl=mid,pr=mid+1;
        while(pow(p[pl].x-pos,2)<=ans && pl>=l) --pl;
        ++pl;
        while(pow(p[pr].x-pos,2)<=ans && pr<=r) ++pr;
        --pr;
        vector <point> v;
        for(int i=pl;i<=pr;i++) v.push_back(p[i]);
        sort(v.begin(),v.end(),cmp);
        for(int i=0;i<v.size();i++) {
            for(int j=i+1;j<v.size();j++) {
                if(pow(fabs(v[i].y-v[j].y),2)>ans) break;
                ans=min(ans,dist2(v[i],v[j]));
            }
        }
        return ans;
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++) {
        cin>>p[i].x>>p[i].y;
    }
    sort(p+1,p+n+1);
    printf("%.4lf
",sqrt(solve(1,n)));
}

以上是关于[P1427] 平面最近点对加强版 - 分治的主要内容,如果未能解决你的问题,请参考以下文章

P1429 平面最近点对[加强版] 随机化

题解平面最近点对(加强版)

Luogu P1429 平面最近点对(加强版)

平面最近点对(加强版)

「LuoguP1429」 平面最近点对(加强版)

洛谷P1257 平面上的最接近点对 数学 分治 排序