平面上的最接近点对
题目描述
给定平面上 nn 个点,找出其中的一对点的距离,使得在这 nn 个点的所有点对中,该距离为所有点对中最小的。
输入格式
第一行一个整数 nn,表示点的个数。
接下来 nn 行,每行两个实数 x,yx,y ,表示一个点的行坐标和列坐标。
输出格式
仅一行,一个实数,表示最短距离,四舍五入保留 44 位小数。
输入输出样例
3
1 1
1 2
2 2
1.0000
说明/提示
数据规模与约定
对于 100\%100% 的数据,保证 1 ≤ n ≤ 10^41≤n≤104,0 ≤ x, y ≤ 10^9,0≤x,y≤109,小数点后的数字个数不超过 66。
分治法求解
分解
对所有的点按照 xx 坐标(或者 yy )从小到大排序(排序方法时间复杂度 O(nlogn))O(nlogn))。根据下标进行分割,使得点集分为两个集合。
解决
递归的寻找两个集合中的最近点对。取两个集合最近点对中的最小值 min(dis_{left},dis_{right})min(disleft,disright)
合并
最近距离不一定存在于两个集合中,可能一个点在集合 A,一个点在集合 B,而这两点间距离小于 disdis。
其中如何合并是关键。根据递归的方法可以计算出划分的两个子集中所有点对的最小距离 disleft,disright,再比较两者取最小值,即 dis=min(dis_{left},dis_{right}) 。那么一个点在集合 A,一个在集合 B中的情况,可以针对此情况,用之前分解的标准值,即按照 x 坐标(或者 y)从小到大排序后的中间点的 x 坐标作为 mid。划分一个 [mid-dis,mid+dis] 区域,如果存在最小距离点对,必定存在这个区域中。
之后只需要根据左边区域 [mid-dis,mid][mid−dis,mid] 的点来遍历右边区域 [mid,mid+dis][mid,mid+dis] 的点,即可找到是否存在小于 disdis 距离的点对。
但是存在一个最坏情况,即通过左右两个区域计算得到的 disdis 距离来划分的第三区域可能包含集合所有的点,这时候进行遍历查找,时间复杂度仍然和 brute forcebruteforce 方法相同,都为O(n^2)