算法三十四:最近点对

描述

给定n个二维平面上的点,求距离最近的一对点,输出他们的距离。

输入

第一行包含一个正整数n。

接下来n行,每行包含两个整数x,y,表示一个点的坐标。

输出

输出距离最近的一对点的距离,保留两位小数。

样例输入

10
7 9
-8 -1
-3 -1
1 4
-3 9
6 -4
7 5
6 6
-6 10
0 8

样例输出

1.41

样例解释

距离最近的点为7和8,距离为(76)2+(56)2=21.41(7-6)2+(5-6)2=2≈1.41

提示

[分治求最近点对。当然也可以用kdtree,虽然应该会超时。]

一. 伪代码


二. 具体实现

#include <bits/stdc++.h>
using namespace std;
// ================= 代码实现开始 =================
typedef double lf;
typedef long long ll;
const int N = 300005;
// 用于存储一个二维平面上的点
struct ip {
    int x, y;
    // 构造函数
    ip(int x = 0, int y = 0) : x(x), y(y) { }
     // 先比较x轴,再比较y轴
    bool operator < (const ip &a) const {
        return x == a.x ? y < a.y : x < a.x;
    }
} a[N], b[N];
// 计算x的平方
ll sqr(const ll &x) {
    return x * x;
}
// 计算点a和点b的距离
lf dis(const ip &a, const ip &b) {
    return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}
lf ans;
//分治求最近点对
//l,r:表示闭区间[l,r]

void solve(int l, int r){
    //边界情况
    if(r - l <= 1){
        if(a[l].y > a[r].y)
            swap(a[l], a[r]);
        if(l != r)
            ans = min(ans,dis(a[l], a[r]));
        return;
    }
    //分治计算两遍
    int mid = (l + r) >> 1;
    int md = a[mid].x;//中间值
    solve(l, mid);
    solve(mid + 1, r);
    //对y轴进行归并排序
    int cnt = 0;
    for(int i = l, j = mid + 1; i <= mid || j <= r;){
        for(; i <= mid && md - a[i].x >= ans; ++i);
        for(; j <= r && a[j].x - md >= ans; ++j);
        if(i <= mid && (j > r || a[i].y < a[j].y))
            b[cnt++] = a[i++];
        else
            b[cnt++] = a[j++];
    }
    //现在b数组
    for(int i = 0; i < cnt; ++i)
        for(int j = i + 1; j < cnt && b[j].y - b[i].y < ans; ++j)
            ans = min(ans, dis(b[i], b[j]));
    cnt = 0;
    for(int i = l, j = mid + 1; i <= mid || j <=r;){
        if(i <= mid &&(j > r || a[i].y < a[j].y))
            b[cnt++] = a[i++];
        else
            b[cnt++] = a[j++];
    }
    memcpy(a + l, b, sizeof(ip) * cnt);
}
// 计算最近点对的距离
// n:n个点
// X, Y:分别表示x轴坐标和y轴坐标,下标从0开始
// 返回值:最近的距离

double getAnswer(int n, vector<int> X, vector<int> Y) {
   for(int i = 0; i < n; ++i)
        a[i+1] = ip(X[i], Y[i]);
   ans = 1e100;
   sort(a + 1,a + 1 + n);
   solve(1, n);
   return ans;
}
// ================= 代码实现结束 =================





猜你喜欢

转载自blog.csdn.net/wydyd110/article/details/80911180