平面最近点对
引入
给定 
下面我们介绍一种时间复杂度为 
过程
与常规的分治算法一样,我们将这个有 
我们先将所有点按照 
并递归下去,求出两点集各自内部的最近点对,设距离为 
现在该合并了!我们试图找到这样的一组点对,其中一个属于 
结合图像,直线 
再根据 
对于 
在点集 

如果我们将 
由此我们得到了合并的步骤:
- 构建集合 - 将 - 对于每个 
注意到我们上文提到了两次排序,因为点坐标全程不变,第一次排序可以只在分治开始前进行一次。我们令每次递归返回当前点集按 
似乎这个算法仍然不优,
复杂度证明
我们已经了解到,
我们再将这个矩形拆分为两个 
我们将一个 

由此,每个正方形中最多有 
实现
我们使用一个结构体来存储点,并定义用于排序的函数对象:
为了方便实现递归,我们引入 upd_ans() 辅助函数来计算两点间距离并尝试更新答案:
下面是递归本身:假设在调用前 a[] 已按 
我们使用 std::inplace_merge() 来执行归并排序,并创建辅助缓冲区 t[],
在主函数中,这样开始递归即可:
推广:平面最小周长三角形
上述算法有趣地推广到这个问题:在给定的一组点中,选择三个点,使得它们两两的距离之和最小。
算法大体保持不变,每次尝试找到一个比当前答案周长 
非分治算法
过程
其实,除了上面提到的分治算法,还有另一种时间复杂度同样是 
我们可以考虑一种常见的统计序列的思想:对于每一个元素,将它和它的左边所有元素的贡献加入到答案中。平面最近点对问题同样可以使用这种思想。
具体地,我们把所有点按照 
- 将所有满足 - 对于集合内满足 - 将 
由于每个点最多会被插入和删除一次,所以插入和删除点的时间复杂度为 
实现
期望线性做法
其实,除了上面提到的时间复杂度为 
首先将点对 随机打乱,我们将维护前缀点集的答案。考虑从前 
记前 
如果这一过程中,答案被更新,我们就重构网格图,否则不重构。在前 
习题
- UVA 10245 "The Closest Pair Problem"[难度:低]
- SPOJ #8725 CLOPPAIR "Closest Point Pair"[难度:低]
- CODEFORCES Team Olympiad Saratov - 2011 "Minimum amount"[难度:中]
- SPOJ #7029 CLOSEST "Closest Triple"[难度:中]
- Google Code Jam 2009 Final "Min Perimeter"[难度:中]
参考资料与拓展阅读
本页面中的分治算法部分主要译自博文 Нахождение пары ближайших точек 与其英文翻译版 Finding the nearest pair of points。其中俄文版版权协议为 Public Domain + Leave a Link;英文版版权协议为 CC-BY-SA 4.0。
贡献者:@Jimmy@Menci@Ancker-0@Anakin@Ir1d@mgt@Xeonacid@Shuhao@邵晨恒@sshwy@countercurrent_time
本页面最近更新:2/3/2023, 12:00:00 AM,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用