最近点对
最近点对
设,表示平面上的一个点。
对于给定的点集,求最近点对。
很容易想到的算法。
计算每一对点的距离,然后取最小值。
但今天看分治的时候看到一种的算法。
我们将点集合按照为第一关键字,为第二关键字的大小升序排列,然后在拆分成集合大小相同的和。
根据分治的想法,最近点对只会有三种情况:
- 两个点都在集合中
- 两个点都在集合中
- 一个在一个在。
前面两种可以递归的寻找,所以问题在于处理第三种情况。
假设情况1的最近点对距离为,情况2的最近点对距离为,。
用上的这张图来观察一下:
对于情况3的情况,所选的点对最好是位于中间中间轴左右的区域内比较好,这个区域就是上图的。
上图是在方向考虑,现在考虑方向。
对于每一个在中的,只需要找到另外一个点,且纵坐标绝对值之差小于,考虑到重复的问题,我们让的纵坐标大于的纵坐标。有一个神奇的证明表示的个数最大为7。
于是对于情况3我们有了一个算法:
- 构建
- 将按照纵坐标排序
- 对于每一个,找到最近距离更新答案
接下来就是使用分治法解决问题了,时间复杂度为【虽然不太会证明这个问题】
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <queue>
#include <cmath>
using namespace std;
#define ll long long
#define pii pair<ll,ll>
const ll N = 1e6+50;
const ll inf = 0x3f3f3f3f;
struct Pt{
double x,y;
}pt[N];
ll n,f[N];
bool cmpxy(const Pt&a,const Pt& b){
return a.x == b.x?a.y<b.y:a.x<b.x;
}
bool cmpy(const ll& a,const ll& b){
return pt[a].y < pt[b].y;
}
double dis(ll i,ll j){
ll dx = pt[i].x-pt[j].x,dy = pt[i].y-pt[j].y;
return sqrt(dx*dx+dy*dy);
}
double close_pair(ll l,ll r){
double h = 1e9+50;
if(l == r) return h;
if(l+1 == r) return dis(l,r);
ll mid = l+r>>1;
double h1 = close_pair(l,mid);
double h2 = close_pair(mid+1,r);
//cout<<h1<<' '<<h2<<endl;
h = min(h1,h2);
ll k = 0;
for(ll i = l;i <= r;i++){
if(fabs(pt[mid].x-pt[i].x) <= h)f[++k] = i;
}
sort(f+1,f+k+1,cmpy);
for(ll i = 1;i <= k;i++){
for(ll j = i+1;j <= k;j++){
if(pt[f[j]].y-pt[f[i]].y >= h) break;
//printf("%lld %lld %.4lf\n",f[i],f[j],dis(f[i],f[j]));
h = min(h,dis(f[i],f[j]));
}
}
//printf("%lld %lld %.4lf\n",l,r,h);
return h;
}
int main() {
//ios::sync_with_stdio(false);
scanf("%lld",&n);
for(ll i = 1;i <= n;i++) scanf("%lf%lf",&pt[i].x,&pt[i].y);
sort(pt+1,pt+n+1,cmpxy);
// for(ll i = 1;i <= n;i++){
// printf("%lf %lf\n",pt[i].x,pt[i].y);
// }
printf("%.4lf\n",close_pair(1,n));
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具