平面最近点对
先证明这个最多6个
我们将
当然实际上,根据下面的代码,由于我们是将
以上算法的时间复杂度是
所以瓶颈是排序,我们想办法消除掉这个排序
一旦有了分治+排序,我们就可以想到利用归并排序的思想来消除复杂度
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=4e5+10;
int n;
struct Node
{
ll x,y;
}temp[N],w[N];
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}
return x*f;
}
bool cmp(Node i,Node j)
{
return i.x<j.x;
}
ll dis(Node i,Node j)
{
return (i.x-j.x)*(i.x-j.x)+(i.y-j.y)*(i.y-j.y);
}
ll cal(int l,int r)
{
if(l==r) return 1e16;
int mid=l+r>>1,cnt=0;
ll Midx=w[mid].x;
ll d=min(cal(l,mid),cal(mid+1,r));
int i=l,j=mid+1;
while(i<=mid||j<=r)//也可以用for循环写,这里只是写的像传统的归并排序罢了
{
while(i<=mid&&(ll)abs(w[i].x-Midx)*abs(w[i].x-Midx)>=d)//先筛选出在虚线框中的点
i++;
while(j<=r&&(ll)abs(w[j].x-Midx)*abs(w[j].x-Midx)>=d)
j++;
if(i<=mid)
{
if(j<=r)
{
if(w[i].y<w[j].y) temp[++cnt]=w[i++];//仍然按照y坐标升序
else temp[++cnt]=w[j++];
}
else temp[++cnt]=w[i++];
}
else if(j<=r) temp[++cnt]=w[j++];
}
for(int i=1;i<cnt;i++)
for(int j=i+1;j<=cnt&&(temp[j].y-temp[i].y)*(temp[j].y-temp[i].y)<d;j++)//最多只有6个点
d=min(d,dis(temp[i],temp[j]));
i=l,j=mid+1;
int k=l;
while(i<=mid&&j<=r)//归并排序
{
if(w[i].y<w[j].y) temp[k++]=w[i++];
else temp[k++]=w[j++];
}
while(i<=mid) temp[k++]=w[i++];
while(j<=r) temp[k++]=w[j++];
for(int i=l;i<=r;i++)
w[i]=temp[i];
return d;
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
w[i].x=read(),w[i].y=read();
sort(w+1,w+n+1,cmp);
printf("%lld",cal(1,n));
return 0;
}
仍然按x排序,只不过
当然有更优的划分,我们设划分为
update 2024.7.14
求三维的最近点对,最后为什么一定是
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构