Ex3_2 最近点对
原文链接http://blog.csdn.net/zyang008/article/details/6175587
分治法
1)算法描述:已知集合S中有n个点,分治法的思想就是将S进行拆分,分为2部分求最近点对。算法每次选择一条垂线L,将S拆分左右两部分为SL和SR,L一般取点集S中所有点的中间点的x坐标来划分,这样可以保证SL和SR中的点数目各为n/2,
(否则以其他方式划分S,有可能导致SL和SR中点数目一个为1,一个为n-1,不利于算法效率,要尽量保持树的平衡性)
依次找出这两部分中的最小点对距离:δL和δR,记SL和SR中最小点对距离δ = min(δL,δR),如图1:

以L为中心,δ为半径划分一个长带,最小点对还有可能存在于SL和SR的交界处,如下图2左图中的虚线带,p点和q点分别位于SL和SR的虚线范围内,在这个范围内,p点和q点之间的距离才会小于δ,最小点对计算才有意义。

对于SL虚框范围内的p点,在SR虚框中与p点距离小于δ的顶多只有六个点,就是图二右图中的2个正方形的6的顶点。这个可以反推证明,如果右边这2个正方形内有7个点与p点距离小于δ,例如q点,则q点与下面正方形的四个顶点距离小于δ,则和δ为SL和SR中的最小点对距离相矛盾。因此对于SL虚框中的p点,不需求出p点和右边虚线框内所有点距离,只需计算SR中与p点y坐标距离最近的6个点,就可以求出最近点对,节省了比较次数。
(否则的话,最坏情形下,在SR虚框中有可能会有n/2个点,对于SL虚框中的p点,每次要比较n/2次,浪费了算法的效率)
代码描述:
1)对点集S的点x坐标和y坐标进行升序排序,获得点集Sx和Sy
2)令δ=∞; //δ为最小点位距离
3)Divide_conquer(Sx,Sy,δ) //分治法
if (Sx.count=1) then δ=∞; //如果Sx中只有一个点,则δ=∞
return δ;
else if(Sx.count=2 and d(Sx.[0],Sx.[1])<δ) //如果Sx中只有2个点,则δ为两点之间距离
δ=d(Sx.[0],)Sx.[1]);
return δ;
else //如果Sx中多于2个点,则将Sx,Sy分治,以中心点画线,将Sx分为左右两部分SxL和SxR,Sy分为SyL和SyR
j1=1,j2=1,k1=1,k2=1;
mid = Sx.count/2; //mid为Sx中的中间点点号
L = Sx.[mid].x; //L为Sx中的中间点x坐标
for(i=1,i<Sx.count,i++)
{
if(i<=mid) //将Sx中间线以左地方的点存入到SxL,新数组保持原来的升序性质
SxL[k1] = Sx[i] k1++;
else //将Sx中间线以右的地方的点存入到SxR,新数组保持原来的升序性质
SxR.count[k2] = Sx[i] k2++;
if(Sy[i].x <L) //将Sy中间线以左地方的点存入到SyL,新数组保持原来的升序性质
SyL[j1] = Sx[i] j1++;
else //将Sy中间线以右地方的点存入到SyR,新数组保持原来的升序性质
SyR[j2] = Sx[i] j2++;
}
δL = Divide_conquer(SxL,SyL,δ); //获取Sx中的的最小点位距离δL
δR = Divide_conquer(SxR,SyR,δ); //获取Sy中的的最小点位距离δR
δ= min (δL,δR);
δ=merge(SyL,SyR,δ); //获Sx中Sy交界处的最小点位距离,并综合 δL和δR 求出点集的最小点位距离δ
return δ;
函数merge(SyL,SyR,δ)
merge(SyL,SyR,δ)
{
i1=1,i2=1;
for(i=1,i<SyL.count,i++) //获取SyL中在左边虚框(距离小于δ)内的点,存入到S'yL中,新数组保持原来的升序性质
{
if(SyL[i].x>L-δ)
then S'yL[i1]= SyL[i], i1++,
}
for(i=1,i<SyR.count,i++) //获取SyR中在右边虚框(距离小于δ)内的点,存入到S'yR中,新数组保持原来的升序性质
{
if(SyR[i].x<L+δ)
then S'yR[i2]= SyR[i], i2++,
}
t=1;
for(i=1,i<S'yL.count,i++)
{
while(S'yR[t].y< S'yL[t].y and t < SyR.count) //获取点集S'yR内距离点S'yL[t]y坐标最接近的点号
{ t++; }
for( j= max(1,t-3), j<=min(t+3,S'yR.count),j++) //计算S'yR中的点与S'yL[t]y坐标相邻的六个点的距离
{
if(d(S'yL[i],S'yL[j])<δ) //如果前两点之间距离小于δ
then δ = d(S'yL[i],S'yL[j]); //则最小点位距离δ为当前两点之间距离
}
return δ
}
3)算法时间复杂度:
首先对点集S的点x坐标和y坐标进行升序排序,需要循环2nlogn次,复杂度为O(2nlogn)
接下来在分治过程中,对于每个S'yL中的点,都需要与S'yR中的6个点进行比较
O(n)= 2O(n/2) + (n/2)*6 (一个点集划分为左右两个点集,时间复杂度为左右两个点集加上中间区域运算之和)
其解为O(n)< O(3nlogn)
因此总的时间复杂度为O(3nlogn),比蛮力法的O(n2)要高效。
Ex3_2 最近点对的更多相关文章
- ICP算法(Iterative Closest Point迭代最近点算法)
标签: 图像匹配ICP算法机器视觉 2015-12-01 21:09 2217人阅读 评论(0) 收藏 举报 分类: Computer Vision(27) 版权声明:本文为博主原创文章,未经博主允许 ...
- Quoit Design---hdu1007(最近点对问题 分治法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:给你n(2<=n<=10^6)个点的坐标,然后找到两个点使得他们之间的距离最小 ...
- 求空间内两条直线的最近距离以及最近点的坐标(C++)
关键词:空间几何 用途:总有地方会用到吧 文章类型:C++函数展示 @Author:VShawn(singlex@foxmail.com) @Date:2016-11-19 @Lab: CvLab20 ...
- HDU 1007Quoit Design(最近点问题)
最近点问题:二维平面中有n(n很大)个点,求出距离最近的两个点 思路:因为n的值很大,所以暴力和dp都行不通了吧!分治法就挺好的. 将区间一半一半的分开,直到分成只有一个点或两个点的时候! 对于只有两 ...
- 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索
第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...
- 计算几何 平面最近点对 nlogn分治算法 求平面中距离最近的两点
平面最近点对,即平面中距离最近的两点 分治算法: int SOLVE(int left,int right)//求解点集中区间[left,right]中的最近点对 { double ans; //an ...
- 2.11 2D平面最近点对问题[closest pair problem]
[本文链接] http://www.cnblogs.com/hellogiser/p/closest-pair-problem.html [题目] 给定平面上N个点的坐标,找出距离最近的两个点之间的距 ...
- ICP(迭代最近点)算法
图像配准是图像处理研究领域中的一个典型问题和技术难点,其目的在于比较或融合针对同一对象在不同条件下获取的图像,例如图像会来自不同的采集设备,取自不同的时间,不同的拍摄视角等等,有时也需要用到针对不同对 ...
- Codeforces Round #245 (Div. 1) 429D - Tricky Function 最近点对
D. Tricky Function Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 codeforces.com/problemset/problem/42 ...
随机推荐
- Could not find default endpoint element that references contract 'wcfXXXXXXXXXXX' in the ServiceMode
Service本身没有问题,但是调用的时候,只在DataAccessSilverlight里引用了,而在主工程WebGISDemo里没有引用服务PowerDataServiceReference,所以 ...
- Spring 单例模式
恶汉模式:Ehan.java package com.cn.danli; /** * 饿汉式单例模式 */ public class Ehan { private static Ehan eh = n ...
- MySQL C API概述
以下列表总结了C API中可用的功能.有关更多详细信息,请参见 第27.8.7节“C API函数描述”中的说明. my_init():在线程安全程序中初始化全局变量和线程处理程序 mysql_affe ...
- JDK源码之数组
序言 <1>栈内存和堆内存当一个方法执行时,每个方法都会建立自己的内存栈,在这方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁.所有在方法中定义的 ...
- Javaweb学习笔记——(十二)——————JSP指令:page指令、include指令、taglib指令,JavaBean,内省,EL表达式
JSP指令JSP指令分类 JSP有三大指令: *page指令 *include指令 *taglib指令 在JSP中没有任何指令是必须的. 但基本上每个JSP都是使用page指令============ ...
- IDAPython教程(三)
在过去两个部分中,我们已经讨论了使用IDAPython让逆向工程更容易一些.这一部分我们来看一下条件断点. 当在IDA中调试时,分析者经常会遇到希望可以在一个特殊的地址中断下来的情况,但这只有在一些特 ...
- MyList 泛型委托
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...
- luogu P3233 [HNOI2014]世界树
传送门 我是什么时候写的这题的qwq 首先,发现关键点的总数被限制了,很自然想到虚树,并且,对于一个关键点,他管理的点显然是一个联通块 然后把虚树先建出来,然后两次dfs,第一次是向祖先更新离每个点最 ...
- Kaldi的关键词搜索(Keyword Search,KWS)
本文简单地介绍了KWS的原理--为Lattice中每个词生成索引并进行搜索:介绍了如何处理OOV--替补(Proxy,词典内对OOV的替补)关键词技术:介绍了KWS的语料库格式:介绍了KWS在Kald ...
- mysql 架构 ~ 异地多活
一 业务异地多活 二 核心思想 多机房提供就近服务,只有当本地机房出现问题时,才会被允许异地机房进行查询和事务操作三 数据库角度 1 多机房之间需要进行数据同步,保证每个机房都保留多机房的全部副本 ...