[转] 最近点对距离问题
转载自: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点之间的距离才会小于δ,最小点对计算才有意义。
对于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)要高效。
例题: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
[转] 最近点对距离问题相关推荐
- POJ3608(旋转卡壳--求两凸包的最近点对距离)
题目:Bridge Across Islands 分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696 考虑如下的算法, 算法的 ...
- 【算法分析与设计】平面最近点对(含最近距离、最近点对、第一次分割点集合的输出)
[问题描述] 给定二维平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小.使用递归与分治策略求解二维平面上的最接近点对问题.假设所有点的集合为S,m为S中所有点的x坐标的中 ...
- CF429D Tricky Function(求解公式、经分析转为求平面最近点对、思维)
整理的算法模板合集: ACM模板 目录 CF429D Tricky Function 题意实际上就是给定长度为 nnn 的一串序列a1,a2,...,ana_1, a_2,...,a_na1,a2 ...
- visio任意区域填充斜线阴影_DX12渲染管线(6) - 级联阴影与距离场阴影
接上一期: 膜力鸭苏蛙可:引擎搭建记录(5) - 距离场 : 建场zhuanlan.zhihu.com 项目地址: MrySwk/GravityEnginegithub.com 上一期,我们完成了 ...
- HDU 4631 Sad Love Story 平面内最近点对
http://acm.hdu.edu.cn/showproblem.php?pid=4631 题意: 在平面内依次加点,求每次加点后最近点对距离平方的和 因为是找平面最近点对...所以加点以后这个最短 ...
- Open3d之计算源点云与目标云的距离
核心函数介绍 compute_point_cloud_distance: 提供了计算从源点云到目标点云的距离的方法.即:它计算源点云中的每个点到目标点云中最近点的距离. 在下面的例子中,展示了使用该函 ...
- 调焦后焦实现不同距离成像_眼的明视与光学调焦
眼的明视与光学调焦 广西桂林地区教育学院 李天镛 人的眼睛是一个由不同介质组成的共轴光学系统,远物或近物发出的进入睛睛的那部分 光线, 经过一系列的反射和折射, 其反射光返回物空间, 折射光都能在视网 ...
- 分治法解决最近点对问题
问题 给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小.严格地说,最接近点对可能多于1对.为了简单起见,这里只限于找其中的一对. 原理(这段为抄袭https://blog. ...
- 计算点到直线/线段的距离
计算目标点到直线/线段的距离,先计算直线/线段上距离目标点最近的点,目标点与最近点的距离,即目标点到直线/线段的距离. 计算最近点: //点到直线的最近点public void GetNear ...
最新文章
- 你的裸照,一键生成,令人害怕的不是算法,是人心!
- 分析决策树算法和逻辑回归算法的不同之处
- mysql 触发器_进阶msql触发器-指南
- webstrom 中 plugins error 设置里 Languages Frameworks里面没有JavaScript?
- dubbo admin默认端口_Dubbo学习(四) Dubbo 从下载到编译成功
- Java生鲜电商平台-微服务架构概述
- HTML+CSS+JS实现 ❤️酷炫的时光隧道旅行动特效❤️
- Android SDK隐藏,如何使用可用的隐藏API和内部API构建Android SDK?
- 东哥再见!我打算 6 月份离职
- terminator安装
- spss因子分析结果解读_因子分析巴特利特球形度检验结果解读
- html点击图片可以放全屏,html:点击图片放大到全屏,再次点击缩回
- 计算机科学与应用论文,计算机科学与应用论文
- python 中的self和cls
- CentOS系统下各文件夹的作用
- 自建CA然后颁发证书给搭建的httpd用
- 微信开发——测试号申请,接口配置,JS接口安全域名,自定义菜单
- 区块链行业前景还好吗?区块链技术有没有经过时间的检验?
- 机器学习 day5 day6 分类问题实战:判断是否为羊毛党
- 大数据和精准投放是广告行业的一场变革
热门文章
- @transactional注解_为啥同一个类中普通方法调用Spring注解方法,注解会失效?看完你就明白,So easy!...
- Hadoop——分布式资源管理框架YARN总结
- nc 模拟服务器_NC集群服务器使用详解
- 字符串排序java_利用Java程序将字符串进行排序与拼接
- TIMING_05 VIVADO环境下的时序约束 之 基本时钟周期约束
- mongodb 数字 _id_MongoDB学习笔记MongoDB简介及数据类型
- python数据库连接类写其他类调用报超时_python面向对象,类,以及连接数据库
- 做一辆超mini平衡自行车,全开源!
- 10年嵌入式工程师经验之谈:对于研发工作的感悟
- 来看看,他的嵌入式之旅!