最近点对问题
1. 问题
最近点对问题
给你n个点的二维坐标,让你去求出这n个点的中两个点相差的最小距离。
以HDU1007为例,这道题大致意思为:给你n个点代表一个物体,给你一个圆环,这个圆环只能套中一个物体,问你这个圆环的最大半径是多少?
2. 解析
这道题简而言之就是让我们求解n个点当中,最近的两个点距离的一半。
这道题暴力求解的话是O(n^2)的复杂度,多组输入,那么会t的。
这道题用分治的思想来做。先将n个点依照x轴的坐标来进行升序排序,然后求mid=(1+n)/2左边的与右边的,然后合并起来。
具体的解释我不是很能描述出来因此将算法上的解释截图下来放在这里。
3. 设计
ld solve(ll l,ll r){
if(l+1==r){
return dist(p[l],p[r]);
}
if(l+2==r){
return get_min(get_min(dist(p[l],p[l+1]),dist(p[l+1],p[r])),dist(p[l],p[r]));
}
ll mid=l+r>>1;
double ans=get_min(solve(l,mid),solve(mid+1,r));
int cnt=0;
for(int i=l;i<=r;i++){
if(p[i].x>=p[mid].x-ans&& p[i].x<=p[mid].x+ans){
p1[++cnt]=p[i];
}
}
sort(p1+1,p1+1+cnt,cmpy);
for(int i=1;i<=cnt;i++){
for(int j=i+1;j<=cnt;j++){
if(p1[j].y-p1[i].y>ans)break;
ans=get_min(ans,dist(p1[i],p1[j]));
}
}
return ans;
}
4. 分析
运行时间递推式为T(n)=2T(n/2)+f(n);应用主定理(a=2,b=2,d=1),因此可知其时间复杂度为O(nlogn).
5. 源码
kitalekita/最小近点问题.cpp at main · kitalekita/kitalekita (github.com)