最近点对算法最近点对问题
二维空间最近点对问题的分治算法伪代码
间的最近距离。
常用的解决方式是分治算法。
以下是分治算法的伪代码表示:假设我们的输入是一组点集,我们将它划分为几个部分,然后在每一部分内应用我们的搜索策略,最后将结果合并以得到整个点的最接近对。
```pythonfunction KPPSearch(points, k)if points is empty or k is 1return (points[0], points[0])else if k is 2return min(minDistance(points[left], points[right]), minDistance(points[right], points[middle]))mid = partition(points)closest = minDistance(points[mid], points[left])if k is 3 or closest is greater than 0return (mid, left)elseleftLeft = minDistance(points[left], points[leftLeft])leftRight = minDistance(points[left], points[leftRight])if leftLeft is greater than 0 and leftRight is greater than 0return (leftLeft, leftRight)elsereturn (left, leftRight)function partition(points)pivot = points[0]left = []middle = []right = []for point in points:if point is less than pivot in Euclidean distance:append(point to left)else:append(point to middle)for point in middle:append(point to right)return pivot, left, middle, right```上述伪代码中的主要步骤包括:分治法的核心步骤`partition`函数用于将数据集分为三部分,并且根据选择的"轴"进行划分;然后在每一个部分内,我们会使用这个方法进行搜索。
最近点对问题
最近点对问题I.一维问题:一、问题描述和分析最近点对问题的提法是:给定平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。
严格的讲,最接近点对可能多于1对,为简单起见,只找其中的1对作为问题的解。
简单的说,只要将每一点与其它n-1个点的距离算出,找出达到最小距离的2点即可。
但这样效率太低,故想到分治法来解决这个问题。
也就是说,将所给的平面上n个点的集合S 分成2个子集S1和S2,每个子集中约有n/2个点。
然后在每个子集中递归的求其最接近的点对。
这里,关键问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。
如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决,但如果这2个点分别在S1和S2中,问题就不那么简单了。
下面的基本算法中,将对其作具体分析。
二、基本算法假设用x轴上某个点m将S划分为2个集合S1和S2,使得S1={x∈S|x<=m};S2={x ∈S|x>m}。
因此,对于所有p∈S1和q∈S2有p<q。
递归的在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设d=min{|p1-p2|,|q1-q2|}。
由此易知,S中的最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{p3,q3},其中p3∈S1且q3∈S2。
如下图所示:S1 S2p1 p2 p3 q1 q2 q3图1 一维情形的分治法注意到,如果S的最接近点对是{p3,q3},即|p3-q3|<d,则p3和q3两者与m的距离不超过d,即|p3-m|<d,|q3-m|<d。
也就是说,p3∈(m-d,m],q3∈(m,m+d]。
由于每个长度为d的半闭区间至多包含S1中的一个点,并且m是S1和S2的分割点,因此(m-d,m]中至少包含一个S中的点。
同理,(m,m+d]中也至少包含一个S中的点。
算法——蛮力法之最近对问题和凸包问题
算法——蛮⼒法之最近对问题和凸包问题 上次的博客写到⼀半宿舍停电了。
然⽽今天想起来补充完的时候发现博客园并没有⾃动保存哦,微笑。
最近对问题 ⾸先来看最近对问题,最近对问题描述的就是在包含n个端的集合中找到距离最近的两个点,当然问题也可以定义在多维空间中,但是这⾥只是跟随书上的思路实现了⼆维情况下的最近对问题。
假设所有讨论的点是以标准的笛卡尔坐标形式(x,y)给出的,那么在两个点P i=(X i,Y i)和P j=(X j,Y j)之间的距离是标准的欧⼏⾥得距离: d(P i,P j)=sqrt( (X1-X2)2+(Y1-Y2)2 )蛮⼒法的思路就是计算出所有的点之间的距离,然后找出距离最⼩的那⼀对,在这⾥增加效率的⼀种⽅式是只计算点下标 i<j 的那些对点之间的距离,这样就避免了重复计算同⼀对点间距离。
下⾯是蛮⼒法解决最近对问题的算法:使⽤蛮⼒法求平⾯中距离最近的两点BruteForceClosetPoints(P)//输⼊:⼀个n(n≥2)的点的列表P,P i=(X i,Y i)//输出:距离最近的两个点的下标index1和index2dmin <— ∞for i <— 1 to n-1 do for j <— i+1 to n do d <— sqrt( (X i-X i)2+(Y j-Y j)2 ) if d<dmin dmin=d; index1=i; index2=j;return index1,index2 该算法的关键步骤是基本操作虽然是计算两个点之间的欧⼏⾥得距离,但是求平⽅根并不是像加法乘法那么简单。
上⾯算法中,开平⽅函数导数恒⼤于0,它是严格递增的,因此我们可以直接只计算(X i-X i)2+(Y j-Y j)2,⽐较d2的⼤⼩关系,这样基本操作就变成了求平⽅。
平⽅操作的执⾏次数是: n(n-1)∈Θ(n2)因此,蛮⼒法解决最近对问题的平均时间复杂度是Θ(n2) 下⾯是该算法的c++代码实现部分,在实现这个算法时,我碰到了三个问题: ⼀是:怎么表⽰⼀个点集,因为最终返回的下标是集合中点的下标,要⽤的数据结构就是⼀维数组,但是点的xy坐标⼜要怎么表⽰呢,这⾥我在头⽂件中创建了struct类型的点结构,该结构拥有的成员变量就是x代表的横坐标和y代表的纵坐标,这样就可以直接创建该结构的⼀位数组进⾏计算了。
用分治法解决最近点对问题:python实现
⽤分治法解决最近点对问题:python实现 最近点对问题:给定平⾯上n个点,找其中的⼀对点,使得在n个点的所有点对中,该点对的距离最⼩。
需要说明的是理论上最近点对并不⽌⼀对,但是⽆论是寻找全部还是仅寻找其中之⼀,其原理没有区别,仅需略作改造即可。
本⽂提供的算法仅寻找其中⼀对。
解决最近点对问题最简单的⽅法就是穷举法,这样时间复杂度是平⽅级,可以说是最坏的策略。
如果使⽤分治法,其时间复杂度就是线性对数级,这样⼤⼤提⾼了效率。
⾸先⽤分治法解决该问题的基本思路可以参考 /lishuhuakai/article/details/9133961 ,说的很详细,但⼤致思路就是先根据x轴把所有点平分,然后分别在每⼀部分寻找最近点对,最后通过⽐较选⼀个最⼩的。
当然其中最核⼼的地⽅是跨域求距离,原⽂写的很清楚,在此就不再赘述了。
以下是代码:from math import sqrtdef nearest_dot(s):len = s.__len__()left = s[0:len/2]right = s[len/2:]mid_x = (left[-1][0]+right[0][0])/2.0if left.__len__() > 2: lmin = nearest_dot(left) #左侧部分最近点对else: lmin = leftif right.__len__() > 2: rmin = nearest_dot(right) #右侧部分最近点对else: rmin = rightif lmin.__len__() >1: dis_l = get_distance(lmin)else: dis_l = float("inf")if rmin.__len__() >1: dis_2 = get_distance(rmin)else: dis_2 = float("inf")d = min(dis_l, dis_2) #最近点对距离mid_min=[]for i in left:if mid_x-i[0]<=d : #如果左侧部分与中间线的距离<=dfor j in right:if abs(i[0]-j[0])<=d and abs(i[1]-j[1])<=d: #如果右侧部分点在i点的(d,2d)之间if get_distance((i,j))<=d: mid_min.append([i,j]) #ij两点的间距若⼩于d则加⼊队列if mid_min:dic=[]for i in mid_min:dic.append({get_distance(i):i})dic.sort(key=lambda x: x.keys())return (dic[0].values())[0]elif dis_l>dis_2:return rminelse:return lmin# 求点对的距离def get_distance(min):return sqrt((min[0][0]-min[1][0])**2 + (min[0][1]-min[1][1])**2)def divide_conquer(s):s.sort(cmp = lambda x,y : cmp(x[0], y[0])) nearest_dots = nearest_dot(s)print nearest_dots测试⼀下,⽐如说要找这些点中最近的⼀对s=[(0,1),(3,2),(4,3),(5,1),(1,2),(2,1),(6,2),(7,2),(8,3),(4,5),(9,0),(6,4)]运⾏⼀下divide_conquer(s),最终打印出[(6, 2), (7, 2)],Bingo。
二分法计算点集最近的两个点及距离
二分法计算点集最近的两个点及距离文章标题:探讨二分法在计算点集中最近的两个点及其距离中的应用在计算机科学和算法领域中,二分法是一种非常常见且有效的算法,它在许多问题的解决中发挥着重要作用。
其中,二分法在计算点集中最近的两个点及其距离时,也有着极其重要的应用。
本文将深入探讨二分法在这一问题中的应用,从简单到复杂、由浅入深地介绍二分法的原理,探讨其在计算最近点对时的实际应用,并分享一些个人观点和理解。
一、什么是二分法让我们简要介绍一下二分法的基本原理。
二分法,英文名为Binary Search,是一种在有序数组中查找特定元素的搜索算法。
其基本原理是每次将待查找区间对半分,然后确定要查找的值在哪一半,从而缩小查找范围,直到找到要查找的值或确定值不存在为止。
二、二分法在计算最近点对中的应用在计算最近点对的问题中,给定一个包含n个点的集合,需要找到集合中距离最近的两个点,并计算它们的距离。
对于这一问题,我们可以借助二分法来解决。
具体而言,我们可以首先根据点的横坐标对点集进行排序,然后利用二分法在排好序的点集中寻找最近点对。
由于排好序的点集在空间中具有一定的顺序关系,因此可以利用这一特性来优化查找过程,从而减少计算量。
在利用二分法查找最近点对时,我们可以将点集等分成两部分,然后分别在左右两部分中寻找最近点对。
然后再考虑中间部分的情况,这样就可以递归地求解最近点对的问题。
通过不断地将点集分割、计算和比较,最终可以找到整个点集中最近的两个点,并计算它们的距离。
三、二分法在计算最近点对中的实际应用二分法在计算最近点对的算法中有着广泛的实际应用价值。
通过巧妙地利用二分法,可以在较快的时间内找到点集中最近的两个点,并计算它们的距离。
这对于许多计算机图形学、空间数据分析等领域都具有重要意义。
在实际应用中,我们可以结合二分法和分治法来处理最近点对的问题,从而提高算法的效率和精度。
通过合理地设计算法流程和数据结构,可以使二分法在计算最近点对问题中发挥出色的效果。
最近点对算法
最近点对算法1. 简介最近点对算法(Closest Pair Algorithm)是一种用于找到平面上最近的两个点的算法。
该算法可以在给定一组点的情况下,找到距离最近的两个点,并计算出它们之间的距离。
最近点对问题在计算几何学、图像处理、数据挖掘等领域中具有广泛应用。
例如,在地理信息系统中,可以使用最近点对算法来查找距离最近的两个地理位置;在机器视觉中,可以使用该算法来寻找图像中距离最接近的两个特征点。
2. 算法思想最近点对算法采用分治策略,将问题划分为多个子问题,并通过递归求解子问题来得到整体解。
其基本思想可以概括为以下步骤:1.将所有点按照横坐标进行排序。
2.将排序后的点集平均划分为左右两部分,分别称为P_left和P_right。
3.分别在P_left和P_right中递归求解最近点对。
4.在左右两部分求得的最近点对中,选择距离更小的那一对作为候选解。
5.在区间[P_left[-1].x, P_right[0].x]内,查找可能的更近点对。
6.比较候选解与新找到的更近点对,选择距离更小的那一对作为最终解。
3. 算法实现3.1 数据结构在实现最近点对算法时,需要定义合适的数据结构来表示点。
常见的表示方法是使用二维数组或类对象。
以下是使用类对象来表示点的示例代码:class Point:def __init__(self, x, y):self.x = xself.y = y3.2 算法步骤3.2.1 排序首先,将所有点按照横坐标进行排序。
可以使用快速排序或归并排序等算法来实现排序功能。
def sort_points(points):# 使用快速排序按照横坐标进行排序# ...3.2.2 分治求解将排序后的点集平均划分为左右两部分,并递归求解最近点对。
def closest_pair(points):n = len(points)# 如果点集中只有两个点,则直接返回这两个点和它们之间的距离if n == 2:return points, distance(points[0], points[1])# 如果点集中只有三个点,则直接计算出最近点对if n == 3:d1 = distance(points[0], points[1])d2 = distance(points[0], points[2])d3 = distance(points[1], points[2])if d1 <= d2 and d1 <= d3:return [points[0], points[1]], d1elif d2 <= d1 and d2 <= d3:return [points[0], points[2]], d2else:return [points[1], points[2]], d3# 将点集平均划分为左右两部分mid = n // 2P_left = points[:mid]P_right = points[mid:]# 分别在左右两部分递归求解最近点对closest_pair_left = closest_pair(P_left)closest_pair_right = closest_pair(P_right)# 在左右两部分求得的最近点对中,选择距离更小的那一对作为候选解if closest_pair_left[1] < closest_pair_right[1]:min_pair, min_distance = closest_pair_leftelse:min_pair, min_distance = closest_pair_right3.2.3 查找更近点对在区间[P_left[-1].x, P_right[0].x]内,查找可能的更近点对。
TSP的几种求解方法及其优缺点
TSP的几种求解方法及其优缺点一、什么是TSP问题旅行商问题,简称TSP,即给定n个城市和两两城市之间的距商,要求确定一条经过各城市当且仅当一次的是短路线。
其图论描述为:给定图G= (V, A),其中V为顶点集,A 为各顶点相互连接组成的边集,设(dij)是由顶点i和顶点j之间的距离所组成的距离矩阵,要求确定一条长度最短的Hamihon回路,即遍历所有顶点当且仅当一次的最短距离。
旅行商问题可分为如下两类:1)对称旅行商问题3j=dji, ni, j=l, 2, 3, - , n);2)非对称旅行商问题(dijHdji, Bi, j=1, 2, 3, - , n)o非对称旅行商问题较碓求解,我们一般是探讨对称旅行商问题的求解。
若对于城市V={V H V2, V n - , %}的一个访问顺序为T={l), b, tj, - , tj, - , tj,A其中衣v (i=l, 2, 3,・・・,□),且记t n+l=tl>则旅行商问题的数学模型为:血工Xzr-l TSP是一个典型的组台优化问题,并且是一个NP完全难题,是诸多领域内出现的多种复杂问题的集中槪括和简化形式,并且已成为各种启发式的搜索、优化算法的间接比较标准。
因此,快速、有效地解决TSP有着重要的理论价值和板高的实际应用价值。
二、主要求解方法基于TSP的问题特性,构造型算法成为最先开发的求解算法,如最近邻点、最近台并、最近插入、晨远插入、最近添加、贪婪插入等。
但是,由于构造型算法优化质長较差,迄今为止巳开发了许多性能较好的改迸型搜索算法,主要有:1)模拟退火算法2)禁忌搜索算法3)Hopficld神经网络优化算法4)蚁群算法5)遗传算法6)混合优化策路2.1模拟退火算法方法1)编码选择:采用描述TSP解的臺常用的一种策略——路径编码。
2)SA状态产生函数的设计:对于基于站径编码的SA状态产生函数操作,可将其设计为:①互换操作(SV7AP);②逆序操作(INV);③插入操作仃NS)。
最近点对问题
算法分析与设计最近对问题最近对问题问题描述:在二维平面上的n 个点中,如何快速的找出最近的一对点,就是最近点对问题。
程序设计思想:1.蛮力法求最近对问题:基本思想:分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计算两次距离,只考虑j i <的那些点对()j i P P ,。
复杂度分析:对于此算法,主要就是算两个点的欧几里得距离。
注意到在求欧几里得距离时,避免了求平方根操作,其原因是:如果被开方的数越小,则它的平方根也越小。
所以复杂度就是求平方,求执行次数为: )()1()(2n O n n n T =-=;即时间复杂度为)(2n O 。
2.分治法求最近对问题:基本思想:用分治法解决最近点对问题,就是将一个问题分解两个子问题,然后递归处理子问题,然后合并。
可能两个点在每个子问题中,也可能两个点分别在两个子问题中,就这两种情况。
则基本过程为:找一条中垂线m (坐位S 集合x 坐标的中位数)把n 个元素分成左右两部分元素,然后分别求得两边的最短距离1d ,2d ,然后取两者中的最小者记为d ,在中线两边分别取d 的距离,记录该距离范围内点的个数,中线左边有L 个元素,右边有R 个元素,分别将两边的点按y 坐标升序排列,在左边集合中每一个点,找右边集合的点,找到与之距离小于d 的点,更新最短距离,直到循环结束,即可求出最短距离。
复杂度分析:应用分治法求解含有n 个点的最近对问题,其时间复杂性可由递推式表示:)()2/(*2)(n f n T n T +=。
由以上分析:合并子问题的解的时间)1()(O n f =。
进而可得分治法求最近对问题的时间复杂度为:)log ()(2n n O n T =。
程序代码:#include <stdio.h>#include <stdlib.h>#include <math.h>#define NUM 1000typedef struct{int x;int y;}N;double distance(N n1,N n2);double minDis(double d1,double d2);double shortestDis(N *data,int length,N *n1 , N *n2); double shortestDis(N *data,int length,N *n1 , N *n2){ int pre,last,middle,median;int i,c1num = 0,c2num = 0,j;N* dataP;N* dataL;N* CP;N* CL;N tn1,tn2;double dis1 ,dis2;// 当只有两个点时,返回最短距离,和点if(length == 2 ){double dis1 = distance(data[0],data[1]);*n1 = data[0];*n2 = data[1];return dis1;}else if(length == 3){// 当只有三个点时,返回最短距离,和点double dis1 = distance(data[0],data[1]);double dis2 = distance(data[1],data[2]);double dis3 = distance(data[0],data[2]);double temp;temp = dis1 < dis2 ? dis1:dis2;temp = temp < dis3 ? temp : dis3;if(temp == dis1){*n1 = data[0];*n2 = data[1];}else if(temp == dis2){*n1 = data[1];*n2 = data[2];}else{*n1 = data[0];*n2 = data[2];}return temp;}middle =length/2;pre = middle;last = length - pre;median = data[middle].x; // 记录中位数dataP = (N*)malloc(sizeof(N)*pre);dataL = (N*)malloc(sizeof(N)*last);CP = (N*)malloc(sizeof(N)*pre);CL = (N*)malloc(sizeof(N)*last);for( i = 0;i < pre ;i++)dataP[i] = data[i];for( i = 0; i< last;i++)dataL[i] = data[i+pre];dis1 = shortestDis(dataP , pre , n1 , n2);dis2 = shortestDis(dataL , last , &tn1 , &tn2);if(dis1 > dis2){*n1 = tn1;*n2 = tn2;}dis1 = minDis(dis1,dis2);for( i = 0; i < pre ; i++)if(dataP[i].x - median < dis1){CP[c1num++] = dataP[i];} // 将在中位数之前的区域中与中位数距离小于最短距离的点放到CP 中for( i = 0; i < last ; i++)if(median - dataL[i].x < dis1){CL[c2num++] = dataL[i];}// 将在中位数之后的区域中与中位数距离小于最短距离的点放到CL 中for(i = 0; i< c1num;i++){for( j =0; j < c2num ; j++){double temp = distance(CP[i],CL[j]);if(temp < dis1){dis1 = temp;*n1 = CP[i];*n2 = CL[j];}}}//依次计算中位数两旁的区域中,每一个点与另外一个区域中的距离,并且记录最短距离return dis1;}double distance(N n1,N n2){return sqrt((n1.x -n2.x)*(n1.x -n2.x) + (n1.y - n2.y)*(n1.y - n2.y));}double minDis(double d1,double d2){double d = d1 < d2 ? d1 : d2;return d;}// 分治法排序void MergeSort(N q[],int num,int mode){int i,nump,numl;N* qPre;N* qLast;if(num == 1 )return;if(num%2&&num != 2){numl = num/2;nump = num/2;nump++;}else{numl = num/2;nump = num/2;}qPre = (N*)malloc(sizeof(N)*nump);qLast = (N*)malloc(sizeof(N)*numl);for(i = 0;i < nump;i++)qPre[i] = q[i];for(i = 0;i<numl;i++)qLast[i] = q[nump+i];MergeSort(qPre,nump,mode);MergeSort(qLast,numl,mode);Merge(qPre,qLast,q,nump,numl,mode);}void Merge(N *pre,N *last,N *total,int nump,int numl,int mode){ int i = 0,j = 0,k = 0;while( i< nump && j< numl ){if(mode == 0){if(pre[i].x > last[j].x ){total[k++] = pre[i++];}else{total[k++] = last[j++];}}else{if(pre[i].y > last[j].y ){total[k++] = pre[i++];}else{total[k++] = last[j++];}}}if(i == nump){for(i = j; i < numl; i++)total[k++] = last[i];}else{for(j = i; j < nump; j++)total[k++] = pre[j];}}void computeShortestDistance(N* data , int num ,int result[4]){FILE *fo;int i,j,l = 0;int *datax,*datay;double dis = 666666,temp;datax = (int*)malloc(sizeof(int)*1000);datay = (int*)malloc(sizeof(int)*1000);for(i =0; i<num ;i++){datax[i] = data[i].x;datay[i] = data[i].y;}for(i = 0;i<num;i++){for(j = i+1;j<num;j++)if((temp = (datax[i] - datax[j])*(datax[i] - datax[j]) + (datay[i] - datay[j])*(datay[i] - datay[j])) < dis){dis = temp;result[0] = datax[i];result[1] = datay[i];result[2] = datax[j];result[3] = datay[j];}}printf("\n蛮力法:\n");printf("shortest dis: %f",sqrt(dis));}void generateDots(int number){FILE *fo;int i,n1,n2;if(!(fo = fopen("data.txt","w"))){printf("open file fail");exit(1);}for(i = 0;i< number;i++){srand((i*i));n1 =rand()%8000;srand(time(NULL)*i*i);n2 = rand()%6000;if(i%2)fprintf(fo,"%d %d\n",n1,n2);elsefprintf(fo,"%d %d\n",n2,n1);}fclose(fo);}int main(){ FILE* fo;N* data;int i;N n1,n2;double dis;int re[4];// 生成数据generateDots(NUM);data = (N*)malloc(sizeof(N)*1000);if(!(fo = fopen("data.txt","r"))){printf("open file fail");exit(1);}for(i = 0;i < NUM;i++){fscanf(fo,"%d %d",&data[i].x,&data[i].y);}fclose(fo);// 合并排序,排好序的数据放置到data 中。
平面最近点对问题
平⾯最近点对问题平⾯最近点对问题正如其名,给定平⾯上的n个点,找出其中的⼀对点,使得这对点的距离在所有点对中最⼩。
⾸先显⽽易见地我们可以得到这个问题的O(n^2)算法,枚举所有点对即可。
但是很显然我们可以注意到,这⾥⾯有很多点对显然不是最优的,那么我们可以想到⼀种剪枝⽅法,就是将只对x坐标差值⼩于当前已知最⼩值的点对进⾏判断(否则必然不是最优解),从⽽减少判断量。
我们考虑使⽤分治来实现这种剪枝,先将平⾯上的点分为两部分,分治求出两部分内部的最近点对距离。
之后我们要做的就是枚举两个集合之间的点对,并与两部分内部的最近点对距离⽐较来得到最近点对距离。
这⾥我们是不需要枚举所有点对的,因为我们已经得到了⼀个两部分各⾃内部最⼩的点对距离,因⽽我们可以结合上⾯的根据x坐标的剪枝⽅法,只枚举分别属于两部分的x坐标差⼩于已知最⼩距离的点对。
这样做的复杂度近似于O(n\log^2n),⾄于怎么得到的……我也不知道。
_(:зゝ∠)_例题:1. Vijos 1012 清帝之惑之雍正链接:2. 平⾯最近点对(加强版)链接:另外附上模板:注意,本模板保留六位⼩数,不能直接⽤于提交上⾯的例题,若要提交请修改输出精度。
1 #include <iostream>2 #include <cstdlib>3 #include <cstdio>4 #include <cstring>5 #include <string>6 #include <sstream>7 #include <cctype>8 #include <cmath>9 #include <algorithm>10#define THE_BEST_PONY "Rainbow Dash"1112using namespace std;13const int maxn=220000,INF=~0u>>1;1415struct Point{16double x,y;17bool operator < (const Point &a) const {18if(x<a.x) return true;19if(x>a.x) return false;20return y<a.y;21 }22 }p[maxn];2324int n;25double ans;2627double DisP(int a,int b){28return sqrt((p[a].x-p[b].x)*(p[a].x-p[b].x)+(p[a].y-p[b].y)*(p[a].y-p[b].y));29 }3031double GetAns(int l,int r){32int mid=(l+r)>>1;33if(l==r) return INF;34if(l==r-1) return DisP(l,r);35double len=min(GetAns(l,mid),GetAns(mid+1,r));36for(int i=mid;i>=l;i--){37if(p[i].x+len<p[mid].x) break;38for(int j=mid+1;j<=r;j++){39if(p[mid].x+len<p[j].x) break;40 len=min(len,DisP(i,j));41 }42 }43return len;44 }4546int main(){47 scanf("%d",&n);48for(int i=0;i<n;i++)49 scanf("%lf%lf",&p[i].x,&p[i].y);50 sort(p,p+n);51 ans=GetAns(0,n-1);52 printf("%.6lf",ans);53return0;54 }Processing math: 0%。
最近点对算法
最近点对算法
最近点对算法是一种计算平面上最近的两个点的算法。
该算法是计算机科学中的一个基本问题,也是计算几何学的研究方向之一。
最近点对问题是指在平面上给定n个点,找出其中距离最近的两个点。
该问题的一个简单暴力解法是对每对点进行距离计算,然后选取距离最小的一对。
但该算法的时间复杂度为O(n^2),当n较大时效率较低。
因此,研究者提出了更高效的算法。
其中一种著名的解法是分治法,该算法的时间复杂度为O(nlogn)。
该算法的思路是将点集分成两个子集,然后递归地计算每个子集中的最近点对,并找出跨越两个子集的最近点对。
除分治法外,还有其他更优秀的最近点对算法,如随机增量法、基于网格的算法等。
最近点对算法在计算机科学、地理信息系统、机器人技术等领域有广泛应用。
- 1 -。
算法设计在计算机科学中的实践应用
算法设计在计算机科学中的实践应用算法设计是计算机科学中的核心概念之一,它对于解决各种实际问题非常重要。
下面将介绍一些算法设计在计算机科学中的实践应用。
1.图像处理和计算机视觉图像处理和计算机视觉领域中广泛应用了各种算法,如图像压缩算法、图像滤波算法、边缘检测算法、目标检测和识别算法等。
这些算法可以帮助人们处理和分析图像数据,提取出图像中的重要信息,并为后续的图像处理和分析任务提供有用的支持。
2.机器学习机器学习是一种通过设计和实现合适的算法来让机器从数据中学习并自动改进性能的方法。
在机器学习中,算法设计是非常重要的。
常见的机器学习算法包括决策树、支持向量机、神经网络等。
这些算法可以用于数据分类、聚类、回归等任务,并在各个领域中得到广泛应用,如自然语言处理、图像识别、推荐系统等。
3.数据库管理系统数据库管理系统是管理和组织大量数据的软件系统,它需要高效的数据存储和检索算法来提高系统性能。
例如,B树和哈希索引是常用的数据检索算法,它们可以快速地定位和检索数据库中的数据。
4.网络路由在互联网中,网络路由算法用于确定数据包从源节点到目的节点的传输路径。
网络路由算法需要考虑路径的带宽、延迟、拥塞等因素,以保证数据的快速和可靠传输。
例如,最短路径算法(如Dijkstra算法)可以用于确定最短路径,而拥塞控制算法可以用于平衡网络流量。
5.计算几何计算几何是研究计算机图形学和机器视觉中几何对象的算法和数据结构。
例如,凸包算法可以用于确定一组点的最小凸多边形,最近点对算法可以用于查找平面上距离最近的点对。
这些算法可以应用在计算机图形学、虚拟现实、三维可视化等领域。
6.操作系统操作系统是管理计算机硬件和软件资源的软件系统,它需要高效的调度和管理算法来提高系统性能。
例如,CPU调度算法(如时间片轮转和优先级调度)可以用于合理分配CPU资源,页面置换算法(如LRU和FIFO)可以用于管理内存中的页面传输。
总之,算法设计在计算机科学中有广泛的实践应用。
求两组点之间的最近点对实验总结
求两组点之间的最近点对实验总结在计算几何学和算法设计中,求两组点之间的最近点对是一个重要且常见的问题。
在这篇文章中,我将从简到繁地探讨这个主题,深入分析求解最近点对的算法,并进行实验总结,以便读者能更深入地理解这一概念。
一、什么是最近点对问题?最近点对问题是指在一个平面上给定n个点,要求在这些点中找到距离最近的两个点。
这个问题在实际中有着广泛的应用,比如计算机视觉中的物体识别、无人驾驶车辆的障碍物检测等都涉及到最近点对的计算。
设计高效的算法来解决最近点对问题具有重要意义。
二、最近点对的暴力解法最简单的方法是通过遍历所有点对,计算它们之间的距离,并找到最小值。
这种暴力解法的时间复杂度为O(n^2),空间复杂度为O(1),虽然简单易懂,但对于大规模的数据集来说效率较低。
三、分治法解决最近点对问题分治法是解决最近点对问题的常见方法,其基本思想是将点集分成两个子集,分别求解最近点对,然后再找出整个点集的最近点对。
在这个过程中需要用到分治、筛选和合并三个步骤。
具体算法流程如下:1. 将点集按照x坐标排序,找到中间线将点集分成左右两个子集。
2. 递归求解左右子集的最近点对。
3. 筛选出距离中线距离小于当前最近距离的点,将它们按照y坐标排序。
4. 在筛选后的点集中,以每个点为中心,向上下各取6个点。
5. 计算这些点之间的距离,更新最近距离。
6. 合并左右子集的结果,得到最终的最近点对。
使用分治法解决最近点对问题的时间复杂度为O(nlogn),效率较高,适用于大规模数据集。
四、实验总结及个人观点在进行最近点对的实验过程中,我发现分治法在处理大规模数据集时具有明显的优势,其算法设计合理、程序实现简单高效。
对于中等规模的数据集,暴力解法也能够得到较好的结果,但对于大规模数据集来说效率明显低于分治法。
我个人认为在解决最近点对问题时,应优先考虑使用分治法,并且可以根据数据规模选择不同的算法来达到更高的效率。
总结来说,求两组点之间的最近点对是一个重要且常见的问题,在实际应用中具有广泛的意义。
【精品】最近点对问题
【精品】最近点对问题点对问题是计算机科学中常见的算法问题,也称为最近点对问题。
其目标是在给定一组点的集合中找到最近的两个点。
在这个问题中,我们将使用分治法来解决最近点对问题。
算法的基本思想是将点集按照x坐标进行排序,并将其分成两个子集。
然后,我们对每个子集递归地应用算法,直到子集中只有一个或两个点。
在这种情况下,我们可以直接计算出最近的点对。
然而,当子集中有超过两个点时,我们需要将问题分解成更小的子问题。
我们选择一个中间点,将点集分成两个子集,并计算出每个子集中的最近点对。
然后,我们需要考虑横跨两个子集的点对。
我们使用一个辅助函数来计算两个子集中的最近点对,并返回最小距离。
在计算最近点对时,我们需要考虑两个子问题。
首先,我们需要找到两个子集中的最近点对。
其次,我们需要找到横跨两个子集的最近点对。
为了找到两个子集中的最近点对,我们可以使用递归地应用相同的算法。
我们将两个子集分别按照y坐标进行排序,并计算出每个子集中的最近点对。
然后,我们需要考虑两个子集之间的点对。
我们将点集中的点按照y坐标进行排序,并找到一个以中间点为中心,距离中间点小于最小距离的点集。
然后,我们可以使用一个循环来比较这些点对,并计算出最小距离。
在计算横跨两个子集的最近点对时,我们需要考虑两个子集之间的点对。
我们将点集中的点按照y坐标进行排序,并找到一个以中间点为中心,距离中间点小于最小距离的点集。
然后,我们可以使用一个循环来比较这些点对,并计算出最小距离。
最后,我们将上述步骤的结果与之前计算的最小距离进行比较,选择较小的距离作为最终的最近点对。
分治法是解决最近点对问题的一个有效方法。
它通过将问题分解成更小的子问题,然后递归地解决这些子问题,最终得到整个问题的解。
在最近点对问题中,我们通过将点集按照x坐标和y坐标进行排序,并使用分治法找到最近点对。
通过使用分治法,我们可以在O(nlogn)的时间复杂度内解决最近点对问题。
这使得它成为处理大规模数据集的理想选择。
凸包-最近点对
1
点集Q的凸包(convex hull)是指一个最小凸多边形, 满足Q中的点或者在多边形 边上或者在其内。右图中由 红色线段表示的多边形就是 点集Q={p0,p1,...p12}的凸包。 2 一组平面上的点,求一 个包含所有点的最小的凸多 边形,这就是凸包问题了。 这可以形象地想成这样:在 地上放置一些不可移动的木 桩,用一根绳子把他们尽量 紧地圈起来,并且为凸边形, 这就是凸包了
2.连结P0 与其他点, 分别计算这些线段 与“竖直向下方向” 的夹角,按照夹角 由小到达的顺序将 各线段的另一端 (一端是P0)标号 为P1、P2、P3…… 如图: (为了使图像更清 晰,现擦去所有线 段)
左转判定 这是经典的计算几何学问题,判断向量p1=(x1,y1)到p2=(x2,y2)是否做左转, 只需要判断x1*y2-x2*y1 的正负,如果结果为正,则从p1 到p2 做左转。 矢量叉积 设有点p0(x0,y0),p1(x1,y1),p2(x2,y2).(p0p1),(p0p2)是共p0的两条向 量,叉积d = (p0p1)x(p0p2) = (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0) 叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的 顺逆时针关系: 若 d > 0 , 则(p0p1)在(p0p2)的顺时针方向。 若 d < 0 , 则(p0p1)在(p0p2)的逆时针方向。(图示方向) 若 d = 0 , 则(p0p1)与(p0p2)共线,但可能同向也可能反向。 相关博客/fivedoumi/article/details/7653128
最近点对
问题描述和分析 最近点对问题的提法是:给定平面上n 个点,找其中的一对点,使得在n个点 组成的所有点对中,该点对间的距离最 小。
最接近点对问题算法
最接近点对问题算法
最接近点对问题是指在平面上给定N个点,找出其中距离最
近的两个点的距离。
可以使用以下算法来解决最接近点对问题:
1. 将所有点按照水平或垂直坐标排序,以便可以更方便地进行后续操作。
2. 将所有点分为两个大致相等的集合,分别称为左集合和右集合。
3. 递归地在左集合和右集合中找出最小距离的点对。
4. 取两个集合中最小距离的点对中较小的距离minDistance。
5. 在以水平坐标为准的线段中,确认是否存在两个点,它们的横坐标之差小于minDistance,并计算它们的距离。
6. 在以垂直坐标为准的线段中,确认是否存在两个点,它们的纵坐标之差小于minDistance,并计算它们的距离。
7. 取步骤5和步骤6中距离的最小值,记为delta。
8. 在左集合和右集合中,找出间距水平线的范围内的点,并按照纵坐标排序。
9. 使用二重循环,依次计算两个集合中的相邻点对之间的距离,直到纵坐标的差大于等于delta。
10. 比较得到的距离和minDistance,取较小的值作为最终的最小距离。
以上算法的时间复杂度为O(nlogn),其中n为点的数量。
使用动态矩形窗求最近点对的几何算法
2 0 1 3年 3月
哈
尔
滨
工 程
大 学
学
报 Vo 1 . 3 4 N . 3 J o u r n a l o f Ha r b i n E n g i n e e in r g Un i v e r s i t y
Ma r . 2 0 1 3
网络出版地址 : h t t p : / / w w w . c n k i . n e t / k c m s / d e t a i l f 2 3 . 1 3 9 0 . U. 2 0 1 3 0 3 0 5 . 0 9 5 7 . 0 1 6 . h t m l
中图分类号 : T P 3 0 1 . 6 文献标志码 : A 文章编号 : 1 0 0 6 - 7 0 4 3 ( 2 0 1 3 ) 0 3 - 0 3 5 0 - 0 8
d i s t a n c e .B y d y n a mi c ll a y r e d u c i n g s i z e o f a r e c t a n g u l a r w i n d o w o f e a c h p o i n t i n e v e r y r e g i o n,t h e n u mb e r o f c a l c u —
( 1 .C o l l e g e o f C o mp u t e r S c i e n c e a n d T e c h n o l o g y , H a r b i n E n g i n e e r i n g U n i v e r s i t y , H a r b i n 1 5 0 0 0 1 , C h i n a ; 2 .S c h o o l o f C o m p u t e r S e i — e n c e T e c h n o l o g y a n d I n f o r m a t i o n E n g i n e e r i n g ,H a r b i n N o ma r l U n i v e r s i t y , Ha r b i n 1 5 0 0 2 5 , C h i n a )
最近点对问题
最近点对问题I.一维问题:一、问题描述和分析最近点对问题的提法是:给定平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。
严格的讲,最接近点对可能多于1对,为简单起见,只找其中的1对作为问题的解。
简单的说,只要将每一点与其它n-1个点的距离算出,找出达到最小距离的2点即可。
但这样效率太低,故想到分治法来解决这个问题。
也就是说,将所给的平面上n个点的集合S 分成2个子集S1和S2,每个子集中约有n/2个点。
然后在每个子集中递归的求其最接近的点对。
这里,关键问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。
如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决,但如果这2个点分别在S1和S2中,问题就不那么简单了。
下面的基本算法中,将对其作具体分析。
二、基本算法假设用x轴上某个点m将S划分为2个集合S1和S2,使得S1={x∈S|x<=m};S2={x ∈S|x>m}。
因此,对于所有p∈S1和q∈S2有p<q。
递归的在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设d=min{|p1-p2|,|q1-q2|}。
由此易知,S中的最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{p3,q3},其中p3∈S1且q3∈S2。
如下图所示:S1 S2p1 p2 p3 q1 q2 q3图1 一维情形的分治法注意到,如果S的最接近点对是{p3,q3},即|p3-q3|<d,则p3和q3两者与m的距离不超过d,即|p3-m|<d,|q3-m|<d。
也就是说,p3∈(m-d,m],q3∈(m,m+d]。
由于每个长度为d的半闭区间至多包含S1中的一个点,并且m是S1和S2的分割点,因此(m-d,m]中至少包含一个S中的点。
同理,(m,m+d]中也至少包含一个S中的点。
最近点对算法 C++
实验三最近点对1.算法设计思路:设共有n个点,找其中距离最近的两点及其距离。
(1)蛮力法:蛮力法的思路是把所有点之间距离比较找出中间最小的。
先假设最短距离是第一个元素和第二个元素的距离,然后求第一个元素与其后的(n-1)个元素各自的距离,若比之前记录的最短距离小则记录当前值···求第i个元素与其后的(n-i)个元素各自的距离,记录之前所得到的所有距离中的最小值,直到计算到第(n-1)个元素与第n个元素的距离,此时记录的距离即为这n个元素中的最短距离。
(2)分治法:分治法是把一个大的问题划分成相似的小问题,采用递归的思想。
找中线把n个元素分成左右两部分元素分别求得两边的最短距离,然后取两者中的最小者记为l,在中线两边分别取l的距离,记录该距离范围内点的个数,中线左边有L个元素,右边有R个元素,求左边元素到右边元素的距离看其是否小于之前记录的最短距离,小则记录下来,此时的右边元素只取y值和左边元素y值距离小于l的(减少循环次数)。
循环结束即可找到最小的距离。
2.程序代码:#include<iostream>#include<cstdlib>#include<ctime>#include<cmath>using std::cout;using std::endl;#define N 5int x[N],y[N],record[N]; //产生原始点数据,x坐标放在x[]中,y坐标放在y[]中。
double Min;//////////////////////////产生随机数组/////////////////////////////void randnum(){int i;srand(time(0));for (i=0;i<N;i++){x[i]=rand()%N;cout<<x[i]<<' ';}cout<<endl;for (i=0;i<N;i++){y[i]=rand()%N;cout<<y[i]<<' ';}cout<<endl;}//////////////////////////////交换数组元素/////////////////////////// void swap(int & a, int & b){int temp=a;a=b;b=temp;}///////////////////////////////求平方///////////////////////////////////int square(int x){return x*x;}/////////////////////////////////////求两点之间距离////////////////////double lengthf(int x1,int y1,int x2,int y2){return sqrt(square(x1-x2)+square(y1-y2));}//////////////////////////////////求两者中最小者////////////////////// double min(double a,double b){if (a>=b)return b;elsereturn a;}////////////////////////////对平面数组排序//////////////////////////// void sort(int A[]){int i,j;for (i=0;i<N;i++)record[i]=i;for (j=1;j<N;j++){i=j;while (i>=0&&A[i]<A[i-1]){swap(A[i],A[i-1]);swap(record[i-1],record[i]); //得到x排序后对应的原y的坐标i--;}}cout<<"排序后的元素数组:"<<endl;for (i=0;i<N;i++)cout<<A[i]<<' ';cout<<endl;for (i=0;i<N;i++)cout<<record[i]<<' ';cout<<endl;}///////////////////////////穷举法找最小点对///////////////////////////////double exhaustion(){int i,j,k1,k2;double num;double length;num=10000;k1=k2=-1;for (j=0;j<N-1;j++){for (i=j+1;i<N;i++){length=lengthf(x[i],y[i],x[j],y[j]);if (length<num){num=length;k1=i;k2=j;}}}cout<<"平面数组最短距离是:"<<endl;cout<<"min="<<num<<endl;cout<<"对应数组下标及点坐标为:"<<endl;cout<<"i="<<k1<<','<<k2<<endl;cout<<"(x1,y1)="<<'('<<x[k1]<<','<<y[k1]<<')'<<endl<<"(x2,y2)="<<'('<<x[k2]<<','<<y[k2]<<')' <<endl;return num;}////////////////////////////////////分治法////////////////////////////////*************************************************************************/double merge(int left,int right){double mlength;if (right==left)mlength=10e-6;if (right==left+1)mlength=lengthf(x[right],y[record[right]],x[left],y[record[left]]); //两个点时求最小值if (right-left==2)mlength=min(min(lengthf(x[right-1],y[record[right-1]],x[left],y[record[left]]),lengthf(x[right],y[re cord[right]],x[left+1],y[record[left+1]])),lengthf(x[right],y[record[right]],x[left],y[record[left]]));//三个点时求最大值return mlength;}double divide(int left,int right){if (right-left<=2){Min=merge(left,right);}else{double l1,l2,mi; //l1记录划分区域后左半面最小距离,l2记录右半面最小距离,min为两者中较小者,m为全部中的最小者int rem1,rem2,l; //记录获得最短距离对应的两个点//int il,jl,ir,jr;int i,j;int R,L;R=L=0; //记录划分小区域后的左半块和右半块个有多少元素l1=l2=Min=100;l=(right-left+1)/2-1; //中线位置///////////////////////////////////////////////////l1=divide(left,l);l2=divide(l+1,right);if (l1<l2){Min=l1;//cout<<"两半面最短距离是:"<<min;else{Min=l2;//cout<<"两半面最短距离是:"<<min;}///////////////////得到右半块元素数R//cout<<"min="<<min<<endl;for (i=l+1;i<N;i++){if (x[i]-x[l]<=Min)R++;else break;}//cout<<"R="<<R<<endl;/////////////////////得到左半块元素数Lfor (i=l;i>=0;i--){if (x[l]-x[i]<=Min)L++;else break;}//cout<<"L="<<L<<endl;if (L!=0&&R!=0){for (i=l-L+1;i<=l;i++)for (j=l+1;j<=l+R;j++){if (y[record[j]]-y[record[i]]<Min||-Min<y[record[j]]-y[record[i]]){mi=lengthf(x[i],y[record[i]],x[j],y[record[j]]);if (mi<Min){Min=mi;rem1=i;rem2=j;}}}// cout<<"min="<<min<<endl;//cout<<"rem1="<<rem1<<endl<<"rem2="<<rem2<<endl;}return Min;}/***********************************************************************///////////////////////////////////主函数///////////////////////////////////int main(){//double a;randnum();cout<<"***************************遍历法*************************"<<endl;exhaustion();cout<<"***************************分治法*************************"<<endl;sort(x);divide(0,N-1);cout<<"元素组中最短距离为:"<<endl;cout<<"min="<<Min<<endl;return 0;}3.实验数据及实验结果:实验数据:随机产生的五个点坐标分别为:(1,3),(4,2),(3,0),(2,0),(0,3)实验结果:用蛮力法得到平面数组最短距离为:min=1用分治法得到平面数组最短距离为:min=14.实验总结:从本次试验中得到的领悟是:分治法事把问题分解成两个相似小问题,子问题和原来的大问题解决方法一样所以可以用递归,分治法重要是找到递归出口,什么时候递归结束,一般都有元素个数的限制。
物流配送优化问题及算法(转自founder)
物流配送优化问题及算法(转⾃founder)物流配送优化问题及算法1、旅⾏商问题(Traveling Salesman Problem, TSP) 这个问题字⾯上的理解是:有⼀个推销员,要到n个城市推销商品,他要找出⼀个包含所有n个城市的具有最短路程的环路。
TSP的历史很久,最早的描述是1759年欧拉研究的骑⼠周游问题,即对于国际象棋棋盘中的64个⽅格,⾛访64个⽅格⼀次且仅⼀次,并且最终返回到起始点。
TSP由美国RAND公司于1948年引⼊,该公司的声誉以及线性规划这⼀新⽅法的出现使得TSP成为⼀个知名且流⾏的问题。
2、中国邮递员问题(Chinese Postman Problem CPP) 同样的问题,在中国还有另⼀个描述⽅法:⼀个邮递员从邮局出发,到所辖街道投递邮件,最后返回邮局,如果他必须⾛遍所辖的每条街道⾄少⼀次,那么他应如何选择投递路线,使所⾛的路程最短?这个描述之所以称为中国邮递员问题,因为是我国学者管梅古⾕教授于1962年提出的这个问题并且给出了⼀个解法。
3、“⼀笔画”问题(Drawing by one line) 还有⼀个⽤图论语⾔的描述⽅式:平⾯上有n个点,⽤最短的线将全部的点连起来。
称为“⼀笔画”问题。
4、配送路线问题(Route of Distribution) TSP问题在物流中的描述是对应⼀个物流配送公司,欲将n个客户的订货沿最短路线全部送到。
如何确定最短路线。
TSP问题最简单的求解⽅法是枚举法。
它的解是多维的、多局部极值的、趋于⽆穷⼤的复杂解的空间,搜索空间是n个点的所有排列的集合,⼤⼩为(n-1)!。
可以形象地把解空间看成是⼀个⽆穷⼤的丘陵地带,各⼭峰或⼭⾕的⾼度即是问题的极值。
求解TSP,则是在此不能穷尽的丘陵地带中攀登以达到⼭顶或⾕底的过程。
5、多回路运输问题(Vehicle Routing Problem, VRP) 多回路运输问题在物流中的解释是对⼀系列客户的需求点设计适当的路线,使车辆有序地通过它们,在满⾜⼀定的约束条件下,如货物需求量、发送量、交发货时间、车辆载重量限制、⾏驶⾥程限制、时间限制等等,达到⼀定的优化⽬标,如⾥程最短、费⽤最少、时间最短,车队规模最少、车辆利⽤率⾼。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{ ( SR[i].y < SR[j].y ) TR[k]=SR[i];
TR[k]=SR[j]; } } (i<=m) { for( l=0;l<=m-i;l) { TR[k+l]=SR[i+l]; // 将剩余SR[i..m]复制到TR } }
{ for( l=0;l<=n-j;l) { TR[k+l]=SR[j+l]; // 将剩余SR[j..n]复制到TR
bool Brute_Force(const Pos& pos ,Closest_Pair& closest_pair , from , to) { for( i=from ;i<=to ;i) { for( j=i+1;j<=to ;j) { double next = Account_Distance_2(pos.p_pair[i] ,pos.p_pair[j]) ;//sqrt( ) (closest_pair.distance > next ) { closest_pair.pair_a = pos.p_pair[i] ; closest_pair.pair_b = pos.p_pair[j] ; closest_pair.distance = next ; } } }
最近点对算法:最近点对问题
疯狂代码 / ĵ:http://VC/Article66512.html
通过代码来学习例子看下面代码: //点结构 typedef struct Pair { x; y; } Pair ; //最近点对结构 typedef struct Closest_Pair { Pair pair_a ,pair_b ; double distance ; } Closest_Pair ; //点对结构 typedef struct Pos { Pair* p_pair ;
double distance ; } Closest_Pair ; typedef struct Pos { Pair* p_pair ; pair_nums ;//点对数目 } Pos ; //-------------------------------------------------------------TR1,s,m,t) ; // 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t]
delete TR2 ; }
// cout << " Hello " ;
} //---------------------------------------------------------------------------
void Comp_CP(const Pos& pos ,Closest_Pair& closest_pair , mid , mid_value) { i,j; distance = sqrt( closest_pair.distance ) ; i = mid ; while( i >= 0 && pos.p_pair[i].x > (mid_value-distance) ) { j = mid ;
}
} } //--------------------------------------------------------------------------void MSort(char sign ,Pair SR ,Pair TR1 ,long s , long t) { // 将SR[s..t]归并排序为TR1[s..t].
( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y) ) ; }
//--------------------------------------------------------------------------void Pr_Pos(ostream& outs ,const Pos& pos ,const Closest_Pair& closest_pair ) { outs << "\n\n\n 随机产生点对如下:\n" ; for( i=0 ;i<pos.pair_nums ;i) { outs << " (" << pos.p_pair[i].x << " , " << pos.p_pair[i].y << " ) " ; ((i+1)%50) { outs << endl ; } } outs << "\n\n 由以上点对可得最近点对为: ( " << closest_pair.pair_a.x << " , " << closest_pair.pair_a.y << " ) ,( " << closest_pair.pair_b.x << " , " << closest_pair.pair_b.y << " ) " ; outs << "\n 该点对距离为:" << closest_pair.distance << endl ; } //---------------------------------------------------------------------------
while( pos.p_pair[j].x < (mid_value+distance) && j < pos.pair_nums ) { ( pos.p_pair[j].y > (pos.p_pair[i].y+distance) || pos.p_pair[j].y < (pos.p_pair[i].y-distance) ) //判断在y轴是否出界 continue ; double next = Account_Distance_2( pos.p_pair[i] ,pos.p_pair[j]);//sqrt( ) (closest_pair.distance > next ) { closest_pair.pair_a = pos.p_pair[i] ; closest_pair.pair_b = pos.p_pair[j] ; closest_pair.distance = next ; cout << "Comp_CP: " << closest_pair.distance << endl ; }
{ mid = (from+to)/2 ; mid_value = pos.p_pair[mid].x ;
Divide_and_Conquer(pos ,closest_pair ,from ,mid) ;
Divide_and_Conquer(pos ,closest_pair ,mid+1 ,to) ; Comp_CP(pos ,closest_pair ,mid ,mid_value) ; }
pair_nums ;//点对数目 } Pos
//蛮力法:分别计算每对点的间距离然后找距离最小那对 bool Brute_Force(const Pos& pos ,Closest_Pair& closest_pair , from , to) { for( i=from ;i<=to ;i) { for( j=i+1;j<=to ;j) { double next= Account_Distance_2(pos.p_pair[i] ,pos.p_pair[j]) ; (closest_pair.distance > next ) { closest_pair.pair_a = pos.p_pair[i] ; closest_pair.pair_b = pos.p_pair[j] ; closest_pair.distance = next ; } } }
true ; }
//-------------------------------------------------------------------------// 对顺序表L作归并排序 void Merge(char sign ,Pair SR ,Pair TR ,long i ,long m ,long n) { // 将有序SR[i..m]和SR[m+1..n]归并为有序TR[i..n] // j,k,l; for( j=m+1,k=i;i<=m&&j<=n;k) // 将SR中记录由小到大地并入TR { (sign'x') { ( SR[i].x < SR[j].x ) TR[k]=SR[i];
(st) { TR1[s] = SR[s]; }
{ // m ; length = t-s+1 ;// Pair* TR2 = Pair[pos.pair_nums]; long m = (s+t)/2; // 将SR[s..t]平分为SR[s..m]和SR[m+1..t] MSort(sign ,SR,TR2,s,m) ; // 递归地将SR[s..m]归并为有序TR2[s..m] MSort(sign ,SR,TR2,m+1,t) ; // 递归地将SR[m+1..t]归并为有序TR2[m+1..t]
; }
# "Head.h" //--------------------------------------------------------------------------typedef RedType ; typedef struct Pair { x; y; } Pair ; typedef struct Closest_Pair { Pair pair_a ,pair_b ;