原文链接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点之间的距离才会小于δ,最小点对计算才有意义。

Figure 2

对于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 (δLR);

δ=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 最近点对的更多相关文章

  1. ICP算法(Iterative Closest Point迭代最近点算法)

    标签: 图像匹配ICP算法机器视觉 2015-12-01 21:09 2217人阅读 评论(0) 收藏 举报 分类: Computer Vision(27) 版权声明:本文为博主原创文章,未经博主允许 ...

  2. Quoit Design---hdu1007(最近点对问题 分治法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:给你n(2<=n<=10^6)个点的坐标,然后找到两个点使得他们之间的距离最小 ...

  3. 求空间内两条直线的最近距离以及最近点的坐标(C++)

    关键词:空间几何 用途:总有地方会用到吧 文章类型:C++函数展示 @Author:VShawn(singlex@foxmail.com) @Date:2016-11-19 @Lab: CvLab20 ...

  4. HDU 1007Quoit Design(最近点问题)

    最近点问题:二维平面中有n(n很大)个点,求出距离最近的两个点 思路:因为n的值很大,所以暴力和dp都行不通了吧!分治法就挺好的. 将区间一半一半的分开,直到分成只有一个点或两个点的时候! 对于只有两 ...

  5. 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索

    第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...

  6. 计算几何 平面最近点对 nlogn分治算法 求平面中距离最近的两点

    平面最近点对,即平面中距离最近的两点 分治算法: int SOLVE(int left,int right)//求解点集中区间[left,right]中的最近点对 { double ans; //an ...

  7. 2.11 2D平面最近点对问题[closest pair problem]

    [本文链接] http://www.cnblogs.com/hellogiser/p/closest-pair-problem.html [题目] 给定平面上N个点的坐标,找出距离最近的两个点之间的距 ...

  8. ICP(迭代最近点)算法

    图像配准是图像处理研究领域中的一个典型问题和技术难点,其目的在于比较或融合针对同一对象在不同条件下获取的图像,例如图像会来自不同的采集设备,取自不同的时间,不同的拍摄视角等等,有时也需要用到针对不同对 ...

  9. Codeforces Round #245 (Div. 1) 429D - Tricky Function 最近点对

    D. Tricky Function Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 codeforces.com/problemset/problem/42 ...

随机推荐

  1. 4.mycat部署

    1.准备工作 mycat依赖Java环境,所以必须安装jdk yum install java-1.8.0-openjdk-devel.x86_64 配置JAVA_HOME环境变量 ls -lrt / ...

  2. GCC编译器原理(三)------编译原理三:编译过程(2-2)---编译之语法分析

    2.2 语法分析 语法分析器(Grammar Parser)将对由扫描器产生的记号进行语法分析,从而产生语法树(Syntax Tree).整个分析过程采用了上下文无关语法(Context-free G ...

  3. 【codeforces 870F】Paths

    Description You are given a positive integer n. Let's build a graph on vertices 1, 2, ..., n in such ...

  4. mysql 创建事件

    mysql 事件说明: 创建事件CREATE EVENT 的语法如下:CREATE EVENT[IF NOT EXISTS] ------------------------------------- ...

  5. 使用Python批量修改文件名

    使用os.rename(fold,newfilename)对文件重命名 # coding:utf-8 import os filename_list = os.listdir('./') for fi ...

  6. 洛谷P1494 【[国家集训队]小Z的袜子】

    纪念自己独立完成的一道省选题(菜鸡如我只会看题解qwq) 还算是一道比较裸的莫队题把,比有的题目简单很多,也很好想怎么O(1)转移,比别的题就多了一个组合数计算(还有gcd??),还没算%意义下,也是 ...

  7. git操作本地仓库基本使用教程

    1.创建仓库 mkdir learngit 2.初始化 cd learngit git init 3.添加文件(把要提交的所有修改放到暂存区(Stage)) git  add 文件 4.提交到仓库(以 ...

  8. BigDecimal实现末尾去掉无用0

    BigDecimal 原生提供了 stripTrailingZeros 方法可以实现去掉末尾的 0,然后使用 toPlainString 可以输出数值,注意这里如果使用 toString()  会变成 ...

  9. Javascript入门(一)弹出方框

    今天要javascript做一个用网页弹出框框的效果,虽然没什么卵用. 效果如图,弹出一个“hello world”的框框. 1. 新建一个html 页面, 如图: <!DOCTYPE html ...

  10. CSL 的字符串(单调栈)

    题目链接:https://ac.nowcoder.com/acm/contest/551/D 题目大意: 题目描述 CSL 以前不会字符串算法,经过一年的训练,他还是不会……于是他打算向你求助. 给定 ...