平面最近对(p1429)

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

题目背景

P7883 平面最近点对(加强加强版)

题目描述

给定平面上 \(n\) 个点,找出其中的一对点的距离,使得在这 \(n\) 个点的所有点对中,该距离为所有点对中最小的。

输入格式

第一行:\(n\) ,保证 \(2\le n\le 200000\)

接下来 \(n\) 行:每行两个整数:\(x\ y\) ,表示一个点的行坐标和列坐标,中间用一个空格隔开。

输出格式

仅一行,一个实数,表示最短距离,精确到小数点后面 \(4\) 位。

输入输出样例 #1

输入 #1

3
1 1
1 2
2 2

输出 #1

1.0000

说明/提示

数据保证 \(0\le x,y\le 10^9\)

AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6;

struct Node{
    int x,y;
} s[maxn];

bool cmp(const Node &a,const Node &b){
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}

bool cmp1(const int &a,const int &b){
    return s[a].y<s[b].y;
}

ll dis(int a,int b){
    return (ll)(s[a].x-s[b].x)*(s[a].x-s[b].x)+(ll)(s[a].y-s[b].y)*(s[a].y-s[b].y);
}

int tmp[maxn];

ll memrge(int l,int r){
    if(l>=r) return LLONG_MAX;
    if(l+1==r) return dis(l,r);
    int mid=(l+r)>>1;
    ll d1=memrge(l,mid);
    ll d2=memrge(mid+1,r);
    ll d=min(d1,d2);
    int t=0;
    for (int i = l; i <= r; i++)
    {
        if ((s[i].x - s[mid].x) * (s[i].x - s[mid].x) < d)
        {
            tmp[t++]=i;
        }
    }
    sort(tmp,tmp+t,cmp1);
    for(int i=0;i<t;i++){
        for (int j = i + 1; j < t && (s[tmp[j]].y - s[tmp[i]].y) * (s[tmp[j]].y - s[tmp[i]].y) < d; j++)
        {
            d=min(d,dis(tmp[i],tmp[j]));
        }
    }
    return d;
}

int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s[i].x>>s[i].y;
    }
    double ans;
    sort(s+1,s+n+1,cmp);
    ans=memrge(1,n);
    ans=sqrt(ans);
    printf("%.4lf\n",ans);
    return 0;
}
posted @ 2025-11-11 09:18  sadmax11  阅读(5)  评论(0)    收藏  举报