转载自:http://www.cnblogs.com/king1302217/archive/2010/07/08/1773413.html

求点集中的最近点对有以下两种方法:

设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

1、蛮力法(适用于点的数目比较小的情况下)

1)算法描述:已知集合S中有n个点,一共可以组成n(n-1)/2对点对,蛮力法就是对这n(n-1)/2对点对逐对进行距离计算,通过循环求得点集中的最近点对:

2)代码描述:

double MinDistance = double.maxvalue;  //设置一个MinDistance存储最近点对的距离,初始值为无穷大

int PointIndex1,PointIndex2; //设置PointIndex1,PointIndex2分别存储最近点对的两个点编号

for (i=1; i< n; i++)    //循环计算n(n-1)/2对点对的距离 {

for (j=i+1; j<=n; j++)      {

double PointDistance = Distance(S[i],S[j]);   //求得point i和point j之间的距离

if PointDistance < MinDistance;  //如果当前点对距离小于最小点对距离,则设置最小点对距离等于当前点对距离

{

MinDistance = PointDistance;

PointIndex1 = i;

PointIndex2 = j;

}

}

}

}       3)算法时间复杂度:算法一共要执行 n(n-1)/2次循环,因此算法复杂度为O(n2)

2、分治法

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)要高效。

例题:http://acm.hdu.edu.cn/showproblem.php?pid=1007

参考代码:http://www.cnblogs.com/hate13/p/4160111.html

转载于:https://www.cnblogs.com/hate13/p/4160056.html

[转] 最近点对距离问题相关推荐

  1. POJ3608(旋转卡壳--求两凸包的最近点对距离)

    题目:Bridge Across Islands 分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696 考虑如下的算法, 算法的 ...

  2. 【算法分析与设计】平面最近点对(含最近距离、最近点对、第一次分割点集合的输出)

    [问题描述] 给定二维平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小.使用递归与分治策略求解二维平面上的最接近点对问题.假设所有点的集合为S,m为S中所有点的x坐标的中 ...

  3. CF429D Tricky Function(求解公式、经分析转为求平面最近点对、思维)

    整理的算法模板合集: ACM模板 目录 CF429D Tricky Function 题意实际上就是给定长度为 nnn 的一串序列a1,a2,...,ana_1, a_2,...,a_na1​,a2​ ...

  4. visio任意区域填充斜线阴影_DX12渲染管线(6) - 级联阴影与距离场阴影

    接上一期: 膜力鸭苏蛙可:引擎搭建记录(5) - 距离场 : 建场​zhuanlan.zhihu.com 项目地址: MrySwk/GravityEngine​github.com 上一期,我们完成了 ...

  5. HDU 4631 Sad Love Story 平面内最近点对

    http://acm.hdu.edu.cn/showproblem.php?pid=4631 题意: 在平面内依次加点,求每次加点后最近点对距离平方的和 因为是找平面最近点对...所以加点以后这个最短 ...

  6. Open3d之计算源点云与目标云的距离

    核心函数介绍 compute_point_cloud_distance: 提供了计算从源点云到目标点云的距离的方法.即:它计算源点云中的每个点到目标点云中最近点的距离. 在下面的例子中,展示了使用该函 ...

  7. 调焦后焦实现不同距离成像_眼的明视与光学调焦

    眼的明视与光学调焦 广西桂林地区教育学院 李天镛 人的眼睛是一个由不同介质组成的共轴光学系统,远物或近物发出的进入睛睛的那部分 光线, 经过一系列的反射和折射, 其反射光返回物空间, 折射光都能在视网 ...

  8. 分治法解决最近点对问题

    问题 给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小.严格地说,最接近点对可能多于1对.为了简单起见,这里只限于找其中的一对. 原理(这段为抄袭https://blog. ...

  9. 计算点到直线/线段的距离

        计算目标点到直线/线段的距离,先计算直线/线段上距离目标点最近的点,目标点与最近点的距离,即目标点到直线/线段的距离. 计算最近点: //点到直线的最近点public void GetNear ...

最新文章

  1. 你的裸照,一键生成,令人害怕的不是算法,是人心!
  2. 分析决策树算法和逻辑回归算法的不同之处
  3. mysql 触发器_进阶msql触发器-指南
  4. webstrom 中 plugins error 设置里 Languages Frameworks里面没有JavaScript?
  5. dubbo admin默认端口_Dubbo学习(四) Dubbo 从下载到编译成功
  6. Java生鲜电商平台-微服务架构概述
  7. HTML+CSS+JS实现 ❤️酷炫的时光隧道旅行动特效❤️
  8. Android SDK隐藏,如何使用可用的隐藏API和内部API构建Android SDK?
  9. 东哥再见!我打算 6 月份离职
  10. terminator安装
  11. spss因子分析结果解读_因子分析巴特利特球形度检验结果解读
  12. html点击图片可以放全屏,html:点击图片放大到全屏,再次点击缩回
  13. 计算机科学与应用论文,计算机科学与应用论文
  14. python 中的self和cls
  15. CentOS系统下各文件夹的作用
  16. 自建CA然后颁发证书给搭建的httpd用
  17. 微信开发——测试号申请,接口配置,JS接口安全域名,自定义菜单
  18. 区块链行业前景还好吗?区块链技术有没有经过时间的检验?
  19. 机器学习 day5 day6 分类问题实战:判断是否为羊毛党
  20. 大数据和精准投放是广告行业的一场变革

热门文章

  1. @transactional注解_为啥同一个类中普通方法调用Spring注解方法,注解会失效?看完你就明白,So easy!...
  2. Hadoop——分布式资源管理框架YARN总结
  3. nc 模拟服务器_NC集群服务器使用详解
  4. 字符串排序java_利用Java程序将字符串进行排序与拼接
  5. TIMING_05 VIVADO环境下的时序约束 之 基本时钟周期约束
  6. mongodb 数字 _id_MongoDB学习笔记MongoDB简介及数据类型
  7. python数据库连接类写其他类调用报超时_python面向对象,类,以及连接数据库
  8. 做一辆超mini平衡自行车,全开源!
  9. 10年嵌入式工程师经验之谈:对于研发工作的感悟
  10. 来看看,他的嵌入式之旅!