算法实验二 分治法 最近点对问题
最近点问题(分治法)
{
if(a[i]>t) t=a[i];
}
return t;
}
/*****************返回数组中某段区域的最小值***********/
template<class Type>
template<class T>
T Select(T a[],int p,int r,int k)
{
if(p==r) return a[p];
int i=Partition(a,p,r),j=i-p+1;
if(k<=j)return Select(a,p,i,k);
int Index(int a[],int p, int q,int x)
{
for(int i=p;i<=q;i++)
{
if(a[i]==x) return i;
}
}
/********************最小对的数值计算*****************/
Type Min(Type a[],int p,int q)
{ Type t=a[p];
for(int i=p;i<=q;i++)
{
if(a[i]<t) t=a[i];
}
return t;
}
/*****************查询数组中某值的下标****************/
//进行中间数的选取
int m=Select(a,p,q,(q-p+1)/2==0?(q-p+1)/2:(q-p+1)/2+1);
最接近点对问题实验报告
最接近点对问题一.实验目的:1.理解算法设计的基本步骤及各步的主要内容、基本要求;2.加深对分治设计方法基本思想的理解,并利用其解决现实生活中的问题;3.通过本次实验初步掌握将算法转化为计算机上机程序的方法。
二.实验内容:1.编写实现算法:给定n对点,在这n对点中找到距离最短的点对。
2.将输出数据存放到另一个文本文件中,包括结果和具体的运行时间。
3.对实验结果进行分析。
三.实验操作:1.最接近点对查找的思想:首先,将所有的点对按照x坐标排序,找到x坐标的中位数,将所有的点对分成三部分,横坐标小于x(S1)、等于x(S2)和大于x(S3)的点对,在求取每部分中的最短距离,利用分治法,一步步地分解为子问题,找到最短距离d。
由于距离最近的两个点可能在不同的区域中,需要进一步判断。
选择S1中的一个点,由于与它相比较的点的距离不可能超过d,故其配对范围为d*2d的矩形,将这个矩形划分为6份2/d*3/d的小矩形,其对角线的长度为5/6d,小于d,故S1中的任意一个点只需和S2中的6个点比较即可,最终确定最短的距离。
2.取中位数:为了减少算法的时间开销,需要将所有的点对进行分组,以中位数为基准,考虑到快速排序的不稳定性,本次排序使用了合并排序。
代码实现:template <class Type>void Merge(Type c[],Type d[],int l,int m,int r){int i = l,j = m + 1,k = l;while((i<=m)&&(j<=r)){if(c[i]<=c[j]) d[k++] = c[i++];else d[k++] = c[j++];}if(i>m) {for(int q=j; q<=r; q++) d[k++] = c[q];}else{for(int q=i; q<=m; q++) d[k++] = c[q];}}template <class Type>void MergeSort(Type a[],Type b[],int left,int right){if(left<right){int i = (left + right)/2;MergeSort(a,b,left,i);MergeSort(a,b,i+1,right);Merge(a,b,left,i,right);//合并到数组aCopy(a,b,left,right);//复制回数组a}}3.数据存入文件:本次对文件的输入没有存入文本文件中,只将输出数据输入到指定的文件夹中,用到了输出流文件。
最近点对分治法
假设在一片金属上钻n 个大小一样的洞,如果洞太近,金属可能会断。
若知道任意两个洞的最小距离,可估计金属断裂的概率。
这种最小距离问题实际上也就是距离最近的点对问题。
如果不用分治法,问题非常容易解决。
也就是蛮力法。
代码如下:#include <stdio.h>#include <math.h>typedef struct TYPE{double x, y;} Point;float dist(Point a,Point b){return (float)sqrt((float)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}float nearest(Point* points, int n) {float temp,near1=10000;int i,j;if(n==1) {printf("不可能");return 0;}else{for(i=0; i<n-1; i++)for(j=i+1; j<n; j++){{temp=dist(points[i],points[j]);near1=(near1>temp)?temp:near1;}}return near1;}}int main(){int n, i;double d;printf("输入点的个数:");scanf("%d", &n);Point a[10000];while (n){for (i = 0; i < n; i++)scanf("%lf%lf", &(a[i].x), &(a[i].y));d = nearest(a,n);printf("%.2lf\n", d);scanf("%d", &n);}return 0;}但是本题是用分治法,我也参考了网上很多资料,他们要求对纵坐标进行排序,可能是为了对求右边的问题的点扫描用for 循环,但我发现那算法就不对,但愿是我的还没有完全明白按纵坐标排序的原因,我参考的资料:/p-198711591.html?qq-pf-to=pcqq.c2c 代码如下:#include <stdio.h>#include <stdlib.h>#include <math.h>#define MAX_POINTS 100000 /*坐标点数的最大值*/#define MAX_TEST 100 /*最大测试次数*/typedef struct { /*定义坐标点*/float x;float y;}Point;float dist(Point a, Point b) { /*求两个坐标点之间的距离*/returnsqrt((float)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}float Nearest(Point* points, int n){ /*求最小距Nearest的函数*/float temp1,temp2,temp3,temp,nearest;float left,right,d;int i,j;if(n==1) printf("距离为0"); /*一个点情形,返回值模拟0。
最近点对问题
最近点对问题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中的点。
分治法解最接近点对问题
算法分析与设计实验报告2014-2015第一学期实验一:用分治法解最接近点对问题指导教师:cccc实验时间:2014年10月28日实验地点:计算中心二楼班级:计ccc学号: 124cc08姓名:杨cc 成绩:实验一用分治法解最接近点对问题的实验一、实验内容:实践名称:用分治法解最接近点对问题的实验时间安排:3学时一、实验目的通过上机实验,要求掌握分治法的问题描述、算法设计思想、程序设计和算法复杂性分析等。
二、实验环境装有Visual C++6.0的计算机。
本次实验共计3学时。
三、实验内容1、熟悉分治算法思想掌握如何创建应用程序。
掌握对最接近点对问题描述,及如何运用算法策略对问题解决和实现。
2、掌握如何编译程序理解编译过程中的错误信息,并掌握如何排错。
3、掌握如何调试程序掌握如何通过设置断点来单步调试程序,如何查看当前变量的值。
4、实验题:完成用分治法解最接近点对问题的实验。
要求:实现该实验结果。
通过该实验题,解决最接近点对问题。
二、实验报告要求1、报告内容包括实验目的、实验内容、实验步骤,实验结果和心得体会五部分;其中实验步骤包括算法分析、算法设计、算法实现主要步骤。
2、截止时间统一为下周二前。
1)算法分析问题描述:已知集合S中有n个点,求这些点中最近的两个点的距离算法分析:分治法的思想就是将S进行拆分,分为2部分求最近点对。
将S拆分左右两部分为SL和SR,L一般取点集S中所有点的中间点的x坐标来划分,这样可以保证SL和SR中的点数目各为n/2,依次找出这两部分中的最小点对距离:δL和δR,记SL和SR中最小点对距离δ = min(δL,δR)以L为中心,δ为半径划分一个长带,最小点对还有可能存在于SL和SR的交界处,如下图2左图中的虚线带,p点和q点分别位于SL和SR的虚线范围内,在这个范围内,p点和q点之间的距离才会小于δ,最小点对计算才有意义。
figure 2对于SL虚框范围内的p点,在SR虚框中与p点距离小于δ的顶多只有六个点,就是图二右图中的2个正方形的6的顶点。
分治法二(平面最近点对)
分治法⼆(平⾯最近点对)上篇⽂章介绍了分治法的概念和基本解题步骤,并附加了⼀个例题帮助⼤家了解分治法的基本思想,在这篇⽂章中,我将对分治法的另⼀个经典问题进⾏分析,希望我的⽂章能够将今天的主题解释清楚。
接下来我将⽤三种不同的⽅法求解“平⾯最近点对”问题。
问题描述:在⼀个平⾯上随机分布着 n 个点,现给定 n 个点的坐标,要求给出最近的两个点之间的距离。
⽅法⼀:原始⽅法题⽬要求求出最近的两点之间的距离,先整理⼀下已知的线索:⾸先点的总个数为 n ;其次已知 n 个点的坐标。
掌握了每个点的坐标,就相当于间接地掌握了任意两点之间的距离。
假设两个点为 A : ( x1 , y1 ) , B : ( x2 , y2 ) ,两点间的距离为 distance ,根据平⾯坐标系中的两点间距离公式可得:distance ^ 2 = ( x1 - x2 ) ^ 2 + ( y1 - y2 ) ^ 2,运⽤该公式对每两个点的距离进⾏计算,并不断更新最⼩值 min_distance 。
核⼼代码为:这个⽅法很直观也最容易想到,不过,由以上的两层循环可知,该⽅法的时间复杂度为 o ( n ^ 2 ) ,当 n 的值不断增⼤时,这个⽅法处理起来就显得⼒不从⼼了。
因此我们必须寻找另⼀种更有效的⽅法,或者在此⽅法上进⾏适当的改进。
接下来⼀起了解⼀下第⼆种⽅法--分治法⽅法⼆:分治法为了做到有理有据,正式叙述解法之前,我得再啰嗦⼏句选择分治法的原因,希望不会引起⼤家的反感。
在本问题中,需要求得最近两点之间的距离,整个问题的规模为 n 个点,不妨将这 n 个点⼀分为⼆,就变成两个求解 n /2 个点规模下最近点对的距离问题,如此不断缩⼩规模,当变成两个点的规模下求解最近点对问题时,显⽽易见,即为这两个点的距离,这样随着问题规模的缩⼩解决的难易程度逐渐降低的特征正是可以⽤分治法解答的问题所具备的特征。
接下来,我们按照分治法解题步骤分割--求解--合并分析这个问题。
用分治法解决最近点对问题: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.蛮力法求最近对问题:1)基本思想:分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计算两次距离,只考虑ji<的那些点对()j i P P,.2)复杂度分析:对于此算法,主要就是算两个点的欧几里得距离。
注意到在求欧几里得距离时,避免了求平方根操作,其原因是:如果被开方的数越小,则它的平方根也越小。
所以复杂度就是求平方,求执行次数为: nnT==;即时间复杂度为)-n)1)O(((2n)O。
(2n2.分治法求最近对问题:1)基本思想:用分治法解决最近点对问题,就是将一个问题分解两个子问题,然后递归处理子问题,然后合并。
可能两个点在每个子问题中,也可能两个点分别在两个子问题中,就这两种情况。
则基本过程为:找一条中垂线m(坐位S集合x坐标的中位数)把n个元素分成左右两部分元素,然后分别求得两边的最短距离1d ,2d ,然后取两者中的最小者记为d ,在中线两边分别取d 的距离,记录该距离范围内点的个数,中线左边有L 个元素,右边有R 个元素,分别将两边的点按y 坐标升序排列,在左边集合中每一个点,找右边集合的点,找到与之距离小于d的点,更新最短距离,直到循环结束,即可求出最短距离.2)复杂度分析:应用分治法求解含有n 个点的最近对问题,其时间复杂性可由递推式表示:)()2/(*2)(n f n T n T +=。
由以上分析:合并子问题的解的时间)1()(O n f =。
进而可得分治法求最近对问题的时间复杂度为:)log ()(2n n O n T =.三、源程序及注释:#include<iostream>#include 〈cstring 〉#include 〈cmath>#include 〈algorithm>#include<time.h>using namespace std ;#define eps 1e-8#define MAXN 10000000#define N 5000struct Point{double x,y;};Point S[N*2],S1[N],S2[N],P1[N],P2[N];double Distance(Point a,Point b){return sqrt((a。
平面最近点对问题(分治)
平⾯最近点对问题(分治)平⾯最近点对问题是指:在给出的同⼀个平⾯内的所有点的坐标,然后找出这些点中最近的两个点的距离.⽅法1:穷举1)算法描述:已知集合S中有n个点,⼀共可以组成n(n-1)/2对点对,蛮⼒法就是对这n(n-1)/2对点对逐对进⾏距离计算,通过循环求得点集中的最近点对2)算法时间复杂度:算法⼀共要执⾏ n(n-1)/2次循环,因此算法复杂度为O(n2)代码实现:利⽤两个for循环可实现所有点的配对,每次配对算出距离然后更新最短距离.for (i=0 ; i < n ;i ++){for(j= i+1 ; j<n ;j ++){点i与点j的配对}}⽅法2:分治1) 把它分成两个或多个更⼩的问题;2) 分别解决每个⼩问题;3) 把各⼩问题的解答组合起来,即可得到原问题的解答。
⼩问题通常与原问题相似,可以递归地使⽤分⽽治之策略来解决。
在这⾥介绍⼀种时间复杂度为O(nlognlogn)的算法。
其实,这⾥⽤到了分治的思想。
将所给平⾯上n个点的集合S分成两个⼦集S1和S2,每个⼦集中约有n/2个点。
然后在每个⼦集中递归地求最接近的点对。
在这⾥,⼀个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。
如果这两个点分别在S1和S2中,问题就变得复杂了。
为了使问题变得简单,⾸先考虑⼀维的情形。
此时,S中的n个点退化为x轴上的n个实数x1,x2,...,xn。
最接近点对即为这n个实数中相差最⼩的两个实数。
显然可以先将点排好序,然后线性扫描就可以了。
但我们为了便于推⼴到⼆维的情形,尝试⽤分治法解决这个问题。
假设我们⽤m点将S分为S1和S2两个集合,这样⼀来,对于所有的p(S1中的点)和q(S2中的点),有p<q。
递归地在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设 d = min{ |p1-p2| , |q1-q2| } 由此易知,S中最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{q3,p3},如下图所⽰。
求最近点对的随机算法.doc
求最近点对的随机算法分治法求解需O(nlogn)时间,而用随机算法求解可达到O(n)时间。
对于给定的平面上的n个点(x i,y i)( i=1,2,…,n)和一个距离δ,以δ为尺寸可以构造一个(逻辑上的)网格,该网格以(min{x i},min{y j})为网格的最左下点,之后以步长δ不断向右、向上伸展为长方形网格;使得(max{x i},max{y j})也含在其中。
由于所有的点均在长方形网格中,最近点对也必在其中。
对每个尺寸为δ×δ的方格,分别向左向上、向右向上、向左向下、Γ(i=1,2,3,4)。
向右向下各扩展一格,可得4个2δ×2δ的方格iδ2定理:设已知平面上的某两点的距离为δ。
若最近点对中的一个点落在某个δ×δ方格δΓ中,Γ(i=1,2,3,4)中,则在上述的4个2δ× 2δ方格iδ2至少有一个同时含有最近点对的两个点。
推论:若已知平面上的某两点的距离为δ,且算法对长方形网格中每一个2δ×2δ方格中的所有点对,均一一计算其距离,则该算法一定可以找出最近点对。
算法:1)在点集S(|S|=n)中随机地取一个子集T,使得|T|=⎣n⎦。
(按随机取样算法的分析,n个中取m个(m≤n)时间为O(n))2)对T中的所有点对逐一计算距离,求出最近点对距离δ(T)。
(点对数为⎣n⎦(⎣n⎦-1)/2,每个点对计算时间为O(1),故总的计算时间为O(⎣n⎦2)= O(n)。
)3)以δ(T)为尺寸构造一个(逻辑上的)长方形网格,(设长方形的横向共有m格,纵向共有r格。
)4) 如果m*r ≤cn (c 可取2~10,取何值合适见后面的讨论),则开设一个m×r 的指针矩阵P 、和一个m×r 的计数矩阵Q , 然后逐一扫描S 中的点s k :如果s k 落在方格ij δΓ中(i,j 分别表示所在方格横向、纵向位置),则把该点放入P[i,j]所指的链表内,Q[i,j]增1,直至n 个点全部检查为止。
用分治算法解平面最接近点对问题
一. 用分治算法解平面最接近点对问题1.题目关于最接近点对问题:给定平面上n个点,找出其中一对点,使得在n个点所构成的所有点对中,该点对的距离最小。
2.程序详细介绍(各模块的功能等)本程序主要包括两个类:类Point和类Ppoint.其中类Point为处理一些的基本数据传递等.类Ppoint为该程序的主要实现模块,该类中有输入点对的函数shuru,对所输入的点对按X轴排序的函数sort,求各点对的距离的函数xiao等.假设S中的点为平面上的点,它们都有2个坐标值x和y。
为了将平面上点集S线性分割为大小大致相等的2个子集S1和S2,我们选取一垂直线l(方程:x=m)来作为分割直线。
其中m为S中各点x坐标的中位数。
由此将S分割为S1={p∈S|px≤m}和S2={p∈S|px>m}。
从而使S1和S2分别位于直线l的左侧和右侧,且S=S1∪S2 。
由于m是S中各点x坐标值的中位数,因此S1和S2中的点数大致相等。
递归地在S1和S2上解最接近点对问题,我们分别得到S1和S2中的最小距离δ1和δ2.此即为该程序的大致算法.3. 程序结构(流程图)该程序的流程图如下所示4. 调试与测试:调试方法,测试结果(包括输入数据和输出结果)的分析与讨论运行该程序时,屏幕上会出现一个界面,首先该界面会提示输入要处理的点对个数,输入点对个数后从键盘输入数字0即可显示出处理后的各个结果,会出现如下结果:5.程序代码(源程序)#include<iostream>#include<cmath>#include<fstream>using namespace std;int i,j,k,d,m,n;double p2,q,s,r,t;class Point //创建一个点类//{public:double x;double y;double getx(){return x;}double gety(){return y;}friend class Ppoint;};class Ppoint{int sum;double juli[10][10];double min[11]; //min[10]用来存放每组中最短的距离//double mini[11]; //mini[10]用来存放每组中距离最短的点对中的第一个点//double minj[11]; //minj[10]用来存放每组中距离最短的点对中的第二个点//Point p[100];Point p1;public:void shuru(){cout<<"请输入要处理的点的个数"<<endl;cin>>sum;for(i=0;i<sum;i++){cout<<"请输入点对"<<endl;cin>>p[i].x;cin>>p[i].y;cout<<p[i].x<<","<<p[i].y<<endl;}}void sort(){cout<<"以下是按x轴上由小到大排序后的点对"<<endl;for(i=0;i<sum-1;i++){for(j=i+1;j<sum;j++){if(p[i].x>p[j].x){p1=p[i];p[i]=p[j];p[j]=p1;}}}for(i=0;i<sum;i++){cout<<p[i].x<<","<<p[i].y<<endl;}}void xiao(){cout<<"以下是对每个模块中的点求距离"<<endl;for(k=0;k<sum/10;k++){cout<<"按任意键继续"<<endl;cin>>i;cout<<"以下是第"<<k<<"个模块中的距离"<<endl;for(i=1;i<10;i++){for(j=0;j<i;j++){r=abs(p[k*10+i].x-p[k*10+j].x);t=abs(p[k*10+i].y-p[k*10+j].y);juli[i][j]=sqrt(r*r+t*t);cout<<juli[i][j]<<"\t";}cout<<endl;}min[k]=juli[k][0],mini[k]=10*k+1,minj[k]=10*k;for(i=1;i<10;i++){cout<<"\n"<<"第"<<i<<"行以前的最小值为"<<min[k]<<endl;for(j=0;j<i;j++){if(juli[i][j]<min[k]){min[k]=juli[i][j];mini[k]=10*k+i;minj[k]=10*k+j;}}}cout<<"\n"<<"这是第"<<k<<"个模块中的结果"<<endl;cout<<"\n"<<"距离最小值为"<<min[k]<<endl;cout<<"\n"<<"距离最小值的第一个点为"<<mini[k]<<endl; //cout<<"距离最小值的第一个点为"<<mini[k]<<endl;//}if(sum%10!=0){k=sum/10;cout<<"输入0显示结果"<<endl;cin>>i;for(i=1;i<sum%10;i++){for(j=0;j<i;j++){m=abs(p[k*10+i].x-p[k*10+j].x);n=abs(p[k*10+i].y-p[k*10+j].y);juli[i][j]=sqrt(m*m+n*n);cout<<juli[i][j];cout<<"\t";}cout<<endl;}min[k]=juli[1][0],mini[k]=10*k+1,minj[k]=10*k;for(i=1;i<sum%10;i++){cout<<"\n"<<"第"<<i<<"行以前的最小值为"<<min[k]<<endl;for(j=0;j<i;j++){if(juli[i][j]<min[k]){min[k]=juli[i][j];mini[k]=10*k+i;minj[k]=10*k+j;}}}cout<<"\n"<<"这是第"<<k<<"个模块中的结果"<<endl;cout<<"\n"<<"距离最小值为"<<min[k]<<endl;cout<<"\n"<<"距离最小值的第一个点为"<<mini[k]<<endl; //cout<<"距离最小值的第一个点为"<<mini[k]<<endl;}}void realmin(){cout<<"\n"<<"几个模块中的最小值是:"<<min[10]<<endl;for(i=0,min[10]=min[0],mini[10]=mini[0],minj[10]=minj[0];i<=sum/10;i++){if(min[i]<min[10]){min[10]=min[i];mini[10]=mini[i];minj[10]=minj[i];}}}void bianjiemin(){cout<<"\n"<<" 包括边界的最小值是:"<<min[10]<<endl;for(i=0;i<sum/10;i++){for(k=9;k>=0;k--)if(p[(i+1)*10].x-p[i*10+k].x<min[10]){for(q=0;q<10;q++)if(p[(i+1)*10+m].x-p[(i+1)*10].x<min[10]){m=abs(p[i*10+k].x-p[(i+1)*10+m].x);n=abs(p[i*10+k].y-p[(i+1)*10+m].y);if(min[10]>sqrt(m*m+n*n)){min[10]=sqrt(m*m+n*n);mini[10]=i*10+k;minj[10]=(i+1)*10+q;}}elsebreak;}elsebreak;}}void shuchu(){i=mini[10];j=minj[10];p2= abs(p[i].x-p[j].x)*abs(p[i].x-p[j].x) ;q= abs(p[i].x-p[j].x)*abs(p[i].x-p[j].x) ;s=sqrt(p2+q);cout<<"\n"<<"最接近点对为"<<"p["<<i<<"]"<<"("<<p[i].x<<","<<p[i].y<<")"<<" "<<"p["<<j<<"]"<<"("<<p[j].x<<","<<p[j].y<<")"<<endl;cout<<"\n"<<"最短距离为"<<min[10];cout<<"\n"<<"最短距离为"<<s;}};int main(){Ppoint x;x.shuru();x.sort();x.xiao();x.realmin();x.bianjiemin();x.shuchu();return 0;}二.设计体会通过这次的课程设计,我对C++程序语言有了更进一步的认识。
求两组点之间的最近点对实验总结
求两组点之间的最近点对实验总结在计算几何学和算法设计中,求两组点之间的最近点对是一个重要且常见的问题。
在这篇文章中,我将从简到繁地探讨这个主题,深入分析求解最近点对的算法,并进行实验总结,以便读者能更深入地理解这一概念。
一、什么是最近点对问题?最近点对问题是指在一个平面上给定n个点,要求在这些点中找到距离最近的两个点。
这个问题在实际中有着广泛的应用,比如计算机视觉中的物体识别、无人驾驶车辆的障碍物检测等都涉及到最近点对的计算。
设计高效的算法来解决最近点对问题具有重要意义。
二、最近点对的暴力解法最简单的方法是通过遍历所有点对,计算它们之间的距离,并找到最小值。
这种暴力解法的时间复杂度为O(n^2),空间复杂度为O(1),虽然简单易懂,但对于大规模的数据集来说效率较低。
三、分治法解决最近点对问题分治法是解决最近点对问题的常见方法,其基本思想是将点集分成两个子集,分别求解最近点对,然后再找出整个点集的最近点对。
在这个过程中需要用到分治、筛选和合并三个步骤。
具体算法流程如下:1. 将点集按照x坐标排序,找到中间线将点集分成左右两个子集。
2. 递归求解左右子集的最近点对。
3. 筛选出距离中线距离小于当前最近距离的点,将它们按照y坐标排序。
4. 在筛选后的点集中,以每个点为中心,向上下各取6个点。
5. 计算这些点之间的距离,更新最近距离。
6. 合并左右子集的结果,得到最终的最近点对。
使用分治法解决最近点对问题的时间复杂度为O(nlogn),效率较高,适用于大规模数据集。
四、实验总结及个人观点在进行最近点对的实验过程中,我发现分治法在处理大规模数据集时具有明显的优势,其算法设计合理、程序实现简单高效。
对于中等规模的数据集,暴力解法也能够得到较好的结果,但对于大规模数据集来说效率明显低于分治法。
我个人认为在解决最近点对问题时,应优先考虑使用分治法,并且可以根据数据规模选择不同的算法来达到更高的效率。
总结来说,求两组点之间的最近点对是一个重要且常见的问题,在实际应用中具有广泛的意义。
算法分析与复杂性理论-实验报告-求最近点对的问题
深圳大学实验报告教务部制1.对于平面上给定的N个点,给出所有点对的最短距离,即,输入是平面上的N个点,输出是N点中具有最短距离的两点。
2.要求随机生成N个点的平面坐标,应用蛮力法编程计算出所有点对的最短距离。
3.要求随机生成N个点的平面坐标,应用分治法编程计算出所有点对的最短距离。
4.分别对N=100,1000,10000,100000 ,统计算法运行时间,比较理论效率与实测效率的差异,同时对蛮力法和分治法的算法效率进行分析和比较。
5.利用Unity3D输出分治算法中间每个步骤的计算结果,并增设help按钮,详细解释算法思想。
算法思想提示1.预处理:根据输入点集S中的x轴和y轴坐标进行排序,得到X和Y,很显然此时X和Y 中的点就是S中的点。
2.点数较少时的情形直接计菊只有三个疽3.点数|S|>3时,将平面点集S分割成为大小大致相等的两个子集S L和S R,选取一个垂直线L作为分割直线,考虑X L和X R,Y L和Y R,这里还需要排序吗?4.两个递归调用,分别求出S L和S R中的最短距离为d i和d r。
5.取d=min(dl, dr),在直线L两边分别扩展d,得到边界区域Y, Y'是区域Y中的点按照y坐标值排序后得到的点集,Y'又可分为左右两个集合Y 'L和Y 'RL.一L<dL+d6.对于Y'L中的每一点,检查Y'R中的点与它的距离,更新所获得的最近距离实验过程及内容:(实验代码已作为附件提交,名为“算法实验二.cpp)当点的数量小丁3时,直接计算,当点的个数大丁3时,采用分治法当N=1时当N=2时只有两个点,最近点对就是这两个点测试数据为(1,1 ) (2,2)预期结果为d=1.414使用蛮力法求最近点对,核心代码如下〃求距离平方的函数double Distinyuish2(Node a t Node b)return ((d.x-b.x)*(a.x-b.x)) + ((a.y-tj.y)*(a.y-b.y));〃蛮力法求最近对uoid BriiteForce(const HList & L,CloseHode & cnode,int begin v int end)For(int i=t)egin;i<=end;i*+)Forfinit j<-end;j + + )double space = Di stinguish2(L.data[i],L.data[j]); iF<sp^ce<cnode.5pact)cnode_a=L.data[l]; cnade.b=L.data[j]; cnode .space=space;(计算两点之间的距离,分别将每个点与其它点的距离求出来,找出最近点距离)当N>3时,使用分治法的情况核心代码如下:;15E 〃当n》3时进行分治<APOIHT *SL-nev fi_POINT[(high-low)/2+1];■[POINT *SR-nev A>0IHT[ (hi^i-low)/2];n)= (high-low)/2; /成曦(组以缺)界划分为茜半j=k=t);for(i=B;i<=high-lou;i*+)if(V[i]*indeK<=n){SL[ ji ] T [i];〃收集左边子集中的最近点对pise{SR[kt+]=Y[i];〃收集右边子集中的最近点对>)closest (K.SL,low,■,al,bl,dl);//i+ 算左边子集的最近点对closes t (X,Sft,m+1,tiigh,ar.br,dr 算右边子靠的最近点对if(dl<dr);b=bl;d=dl;}else(a=ar;b=tjr ;d=dr;POIlfT *2=new POI NT[higti-low+1 ];k=o;For(i=B;i<=t*igh-lcw;i*+)//收集距离中线?寤小于U的元素,保存S懒组?中(iF(f=abstX[n] .x-V[l] .x)<d>2(k].x=V[i],x;£[k^+].y=V[i]^:for(i-l;l<k;l++)< far(j=i>1;(-y-Z[i] j++)dl=aist(Z[i]^[j]);{a = 2[iJ;b - Z[j];ri = d) ■当N=6时,给定一组测试数据下面随机生成N个点的平面坐标,求解最近点对。
【精品】最近点对问题
【精品】最近点对问题点对问题是计算机科学中常见的算法问题,也称为最近点对问题。
其目标是在给定一组点的集合中找到最近的两个点。
在这个问题中,我们将使用分治法来解决最近点对问题。
算法的基本思想是将点集按照x坐标进行排序,并将其分成两个子集。
然后,我们对每个子集递归地应用算法,直到子集中只有一个或两个点。
在这种情况下,我们可以直接计算出最近的点对。
然而,当子集中有超过两个点时,我们需要将问题分解成更小的子问题。
我们选择一个中间点,将点集分成两个子集,并计算出每个子集中的最近点对。
然后,我们需要考虑横跨两个子集的点对。
我们使用一个辅助函数来计算两个子集中的最近点对,并返回最小距离。
在计算最近点对时,我们需要考虑两个子问题。
首先,我们需要找到两个子集中的最近点对。
其次,我们需要找到横跨两个子集的最近点对。
为了找到两个子集中的最近点对,我们可以使用递归地应用相同的算法。
我们将两个子集分别按照y坐标进行排序,并计算出每个子集中的最近点对。
然后,我们需要考虑两个子集之间的点对。
我们将点集中的点按照y坐标进行排序,并找到一个以中间点为中心,距离中间点小于最小距离的点集。
然后,我们可以使用一个循环来比较这些点对,并计算出最小距离。
在计算横跨两个子集的最近点对时,我们需要考虑两个子集之间的点对。
我们将点集中的点按照y坐标进行排序,并找到一个以中间点为中心,距离中间点小于最小距离的点集。
然后,我们可以使用一个循环来比较这些点对,并计算出最小距离。
最后,我们将上述步骤的结果与之前计算的最小距离进行比较,选择较小的距离作为最终的最近点对。
分治法是解决最近点对问题的一个有效方法。
它通过将问题分解成更小的子问题,然后递归地解决这些子问题,最终得到整个问题的解。
在最近点对问题中,我们通过将点集按照x坐标和y坐标进行排序,并使用分治法找到最近点对。
通过使用分治法,我们可以在O(nlogn)的时间复杂度内解决最近点对问题。
这使得它成为处理大规模数据集的理想选择。
算法设计--蛮力法 分治法求最近对问题(C++实现)
算法设计--蛮力法&&分治法求最近对问题(C++实现)最近对问题?设p1=(x1,y1), p2(x2,y2), ....,pn=(xn,yn)是平面上n个点构成的集合S,最近对问题就是找出集合S中距离最近的点对。
两种算法思想:1. 蛮力法:顾名思义,利用正常的思维,使用强硬的方式求解出结果。
2. 分治法:分治,分而治之,把大问题分解为小问题,主要有三个过程:划分、求解子问题、合并。
直接上代码:蛮力法求解最近对问题:[cpp]view plaincopy1.#include "iostream"2.#include "math.h"3.#include "time.h"4.#include "stdlib.h"ing namespace std;6.struct P7.{8.int x;9.int y;10.};11.double ClosePoints(int n,P a[],int &index1,int &index2)12.{13.double d;14.double Dist=10000;15.for (int i=0;i<n-1;i++)16. {17.for (int j=i+1;j<=n-1;j++)18. {19. d=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);20.if(d<=Dist)21. {22. Dist=d;23. index1=i;24. index2=j;25. }26. }27. } return Dist;28.}29.void main (void)30.{31.clock_t start,end;32.int g;33.int s,e;34. P a[10000];35.for (int i=1;i<4;i++)36. {37. cout<<"输入坐标的个数(10000以内)";38. cin>>g;39. srand(time(NULL));40.for (int r=0;r<g;r++)41. {42. a[r].x=rand()%(g-123);43. a[r].y=rand()%(g-1234);44. }45. start=clock();46.double w=ClosePoints(g,a,s,e);47. end=clock();48. cout<<"最近的两个点是:P1("<<a[s].x<<","<<a[s].y<<") P2("<<a[e].x<<","<<a[e].y<<")"<<endl; cout<<"距离是:"<<sqrt(w)<<endl;49. cout<<"蛮力法求最近对用时:"<<(double)(end-start)/CLOCKS_PER_SEC<<"ms"<<endl;50. cout<<"============================================================="<<endl;51. }52.}分治法求解最近对问题:[cpp]view plaincopy1.#include<iostream>2.#include "cstdio"3.#include "cstring"4.#include "math.h"5.#include "time.h"6.#include "stdlib.h"7.#include "algorithm"ing namespace std;9.#define eps 1e-810.#define N 1000011.//定义一个保存坐标的结构体12.struct point13.{14.double x,y;15.};16.17.point node[N * 2];18.point d[N];19.point c[N];20.point b[N];21.int cmp(point a, point b) //比较两点之间的y值22.{23.return a.y < b.y;24.}25.int cmp1(point a, point b)26.{27.if(a.x != b.x)28.return a.x < b.x;29.return a.y < b.y;30.}31.double min(double a, double b) //求a和b两者较小值32.{33.return a > b? b:a;34.}35.36.double dx(double x1, double x2)37.{38.if((x1 - x2) > eps && (x1 - x2) < eps)39. {40.return 0;41. }42.else if(x1 > x2)43. {44.return x1 - x2;45. }46.else if(x1 < x2)47. {48.return x2 - x1;49. }50.}51.52.double ds(point a, point b) //求两点之间的距离53.{54.return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));55.}56./**57.* 最近对问题58.* 三种情况:59.* 1.在子集S1中60.* 2.在自己S2中61.* 3.最近的两个点分别在子集S1和S2中62.*/63.double closestPoints(point node[], int n)64.{65.int i, j;66.int Dist = 99999; //无穷大数67.if(n < 2) //只有一个点,不存在最近对68.return 0;69.int m = (n - 1) / 2; //m是各个坐标的中位数70.for(i = m + 1; i < n; i++)71. {72. b[i].x = node[i].x;73. b[i].y = node[i].y;74. }75.//划分为两个子问题,递归求解子问题76.double d1 = closestPoints(node, m + 1); //得到S1中的最近距离d177.double d2 = closestPoints(b, n - m - 1); //得到S2中的最近距离d278.double dm = min(d1, d2); //求得d1与d2两者之间较小值79.int f,p; //记录点的个数80. p = 0;81.for(i = 0; i <= m; i++) //找出S1中与x=m的距离小于dm的所有点,保存在结构体c当中82. {83.if(dx(node[i].x,node[m].x) < dm)84. {85. c[p].x = node[i].x;86. c[p].y = node[i].y;87. p++;88. }89. }90. f=0;91.for(i = m + 1; i < n; i++) //找出S2中与x=m的距离小于dm的所有点,保存在结构题d当中92. {93.if(dx(node[i].x, node[m].x) < dm)94. {95. d[f].x = node[i].x;96. d[f].y = node[i].y;97. f++;98. }99. }100.101. sort(c, c+p,cmp); //按照y轴的坐标值升序排列102. sort(d, d+f,cmp);103.double ret = Dist;104.for(i = 0; i < p; i++) //遍历比较分别在S1和S2中两点之间的距离105. {106.for(j = 0; j < f; j++)107. {108.double ans = ds(c[i], d[j]);109. ret = min(ret, ans); //得出最近对距离110. }111. }112.return min(ret, dm); //返回第三种情形与前两种情形较小值113.}114.int main(void)115.{116.int n,i;117.for(int w=0;w<6;w++)118. {119. cout<<"输入坐标的数目:"<<endl;120. cin>>n;121. srand((unsigned)time(NULL));122.for(i=0;i<n;i++)123. {124. node[i].x=rand()/(double)(RAND_MAX/10000);125. node[i].y=rand()/(double)(RAND_MAX/10000);126. }127. sort(node,node+n,cmp);128.clock_t start,end;129. start=clock();130. closestPoints(node,n); //系统调用十次分治法函数。
最接近点对问题_分治法
最接近点对问题_分治法⼀、问题描述给定平⾯上的n个点,找其中的⼀对点,使得在n个点组成的所有点对中该点对间的距离最⼩。
⼆、解题思路及所选算法策略的可⾏性分析思路:利⽤分治法来解决问题。
递归⼦结构求最接近点对总体可分为⼏个步骤:1、当问题规模⼩于20,直接求解最⼩点对2、将n个点组成的集合S分成2个⼦集S1和S23、递归求出两个⼦集中的最接近点对并⽐较出最⼩点对,记录距离dmin4、以X坐标为基准找到所有点中线,在中线附近找出相距可能⼩于dmin的点对点,记录于S3和S45、求S3和S4每点对距离,和dmin进⾏⽐较,求解最接近点对策略可⾏性分析:设直线l上有2m个点,以m为中点将l分割成两条线段dl,dr,然后求出dl和dr这两点条线段中的最⼩点距d1,d2,此时d=min{d1,d2},再通过计算出dl线段的中最⼤点与dr线段中的最⼩点之间的距离D,最⼩距离则为min{d,D}.⼆维情况与此相似,最⼤的区别只是对于中线位置的点,⼆维情况只是针对中线旁好多可能点,再在Y轴⽅向上进⾏点的筛选,以减少平⽅计算次数。
三、伪代码描述及复杂度分析Public static double closestPoint(S){1、⾸先,递归结束条件,当数组长度在⼀定范围内时直接求出最近点,蛮⼒求解2、求所有点在X坐标中的中位数midX3、以midX为界将所有点分成两组分别存放在两个表中4、将两张表转化为数组类型,并分别按X坐标升序排列5、求S1中的最近距离的两个点6、求S2中的最近距离的两个点7、求两最近距离的最⼩值8、在S1、S2中收集距离中线⼩于d1的点,分别存放于两个表中9、分别将表T3、T4转换为数组类型的S3、S4,并将其分别按Y坐标升序排列10、求解S3、S4两者之间可能的更近(相⽐于d1)距离 , 以及构成该距离的点}复杂度分析:设算法耗时T(n)。
算法第1步、第2步、第3步和第8步⽤了O(n)时间。
分治 最近点对 证明过程
分治最近点对证明过程分治算法是一种将问题分解为更小的子问题,并通过递归解决子问题,最后将子问题的解合并起来得到原问题解的方法。
最近点对问题是指在一个给定的点集中,找到距离最近的两个点的问题。
在本文中,我们将使用分治算法来解决最近点对问题,并对其正确性进行证明。
我们需要明确最近点对问题的定义。
给定一个点集P,我们需要找到其中两个点p和q,使得它们的距离d(p,q)最小。
距离可以使用欧氏距离或其他度量方式来定义。
我们的目标是设计一个高效的算法来解决这个问题。
分治算法的基本思想是将问题分解为更小的子问题,并通过递归解决子问题。
在最近点对问题中,我们可以将点集P划分为两个较小的子集P1和P2,分别包含点集P的前一半和后一半的点。
然后,我们分别在P1和P2中递归地找到最近点对。
假设在P1和P2中分别找到的最近点对是(p1,q1)和(p2,q2)。
接下来,我们需要考虑P1和P2之间的最近点对。
我们可以观察到,P1和P2中的点到分割线的距离不能超过d1和d2,其中d1和d2分别是P1和P2中找到的最近点对的距离。
因此,我们只需要考虑距离分割线小于d的点。
我们可以将P1和P2按照x轴坐标排序,并找到中间点mid。
然后,我们可以构建一个矩形区域,将其划分为两个部分,分别包含P1和P2的点。
我们只需要在这个矩形区域中找到距离分割线小于d 的点对。
在这个矩形区域中,我们可以按照y轴坐标排序点,并使用滑动窗口的方法来找到距离最近的点对。
具体来说,我们可以从矩形区域的顶部开始,依次考虑每个点,并计算它与后面d/d2个点的距离。
如果找到了距离更小的点对,则更新最近点对的距离。
我们将在P1、P2和跨越分割线的点中找到最近的点对,并返回其距离。
通过以上步骤,我们可以使用分治算法来解决最近点对问题。
接下来,我们将证明该算法的正确性。
我们可以观察到,如果两个点p和q是最近点对,并且它们在分割线的同一侧,那么它们必定在P1或P2中。
最近对问题
《算法设计与分析》实验报告二学号:姓名:日期:得分:一、实验内容:使用递归算法求解平面上n个点组成的集合中的最近点对。
二、所用算法的基本思想及复杂度分析:使用分治法解决最近点对问题就是将集合S分成两个子集是S1和S2,每个子集中有N/2个点。
然后再每个子集中递归的求其最接近的点对,求出每个子集的最接近点对后,如果集合S中最接近的点对都在两个子集中,问题解决。
当两个点分别在两个子集中时,则最近点对为S1和S2的最接近点。
其时间复杂度为O(nlogn)三、源程序及注释:#include<iostream>#include<algorithm>#include<cmath>using namespace std;struct Point{double x;double y;};double distance(Point a,Point b)//求两点之间距离函数{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}bool cmp_x(Point a,Point b)//比较两点的x坐标{return b.x>a.x;}double ClosestPoints(Point P[],int n,Point &a,Point &b)//n是输入点的个数 a,b表示最近点对,d记录最小距离{double d1,d2,m;//d1为p1的最近距离,dr是p2的最近距离,m表示最近点对在p1,p2时的最近距离int i=0,l=0,r=0,k=0,j=0;Point a1,b1,a2,b2;int center=n/2;double d;if(n<2)return 9999999;if(n==2)//只有两个点的时候{d=distance(P[0],P[1]);a=P[0];b=P[1];}else //当n>2时,采用递归{Point *p1=new Point[n]; //p1是左边的子集,p2是右边的子集Point *p2=new Point[n];sort(P,P+n,cmp_x); //对集合中的点按照x坐标大小排序double m=P[(n-1)/2].x; //x坐标的中位点for(i=0;i<center;i++) //构造p1和p2,使得p1中点的x坐标小于m,s2中点的x坐标大于mp1[l++]=P[i];for(i=center;i<n;i++)p2[r++]=P[i];d1=ClosestPoints(p1,l,a1,b1);//使用递归求s1,s2中的最近点对d2=ClosestPoints(p2,r,a2,b2);if(d1<d2){d=d1;a=a1;b=b1;}else{d=d1;a=a2;b=b2;}Point *p3=new Point[n]; //最近的两个点在两个子集中for(i=0;i<=n;i++){if(abs(P[i].x-middle)<d) //将p[]距离小于d的点放到p3中{p3[k].x=P[i].x;p3[k++].y=P[i].y;}}for(i=0;i<k ;i++) //对p1中的点p,在p2中查找与点p的y坐标距离小于d的点,并求出最小值;{for(j=i+1;(j<k)&&(abs(p3[i].y-p3[j].y)<d);j++){m=distance(p3[i],p3[j]);if(m<d){d=m;a=p3[i];b=p3[j];}}}}return d;}void main(){int n;Point a,b;double d;printf("输入点的个数:");scanf("%d",&n);Point *point=new Point[n];printf("输入点集:");for(int i=0;i<n;i++){scanf("%lf%lf",&point[i].x,&point[i].y);}d=ClosestPoints(point n,a,b);printf("最近点对是:(%.2lf,%.2lf),(%.2lf,%.2lf)",a.x,a.y,b.x,b.y);printf("\n最近距离:%lf\n",d);}四、运行输出结果:五、调试和运行程序过程中产生的问题、采取的措施及获得的相关经验教训:1、在对点集中的数据按照x的坐标排序时,一开始使用快速排序,代码较长复杂,然后经查询使用了sort和cmp函数,简便了排序过程。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法分析与设计实验二
分治法
主要内容
•实验目的
•主要实验仪器设备和环境•实验内容
•实验要求
•注意点
实验目的
•理解分治法的基本思想
•针对特定问题,可以设计出分治算法进行求解
主要实验仪器设备和环境
•每位学生一台计算机
•计算机的操作系统为
–windows 2000或Windows XP
•工具软件
–C++ IDE,JAVA IDE
实验内容二最近点对问题
•问题描述
–对于平面上给定的N个点,给出所有点对的最短距
离
–即,输入是平面上的N个点,输出是N点中具有最短距离的两点
•现要求随机生成N个点的平面坐标,应用穷举法编程计算出所有点对的最短距离
•现要求随机生成N个点的平面坐标,应用分治法编程计算出所有点对的最短距离
实验要求
•编程语言可以用C,C++或者JAVA,关键步骤必须有注释
•实验报告必须包含以下内容:算法设计的基本思路、程序清单以及针对测试数据的运行结果•实验报告电子版请发至seualgo@,Email标题:“学号姓名算法实验二最近点对”,附件请不要压缩,实验报告名:“学号姓名算法实验二最近点对”
注意点
•随机数的生成问题
•求解最近点对问题时的分治策略•分解后子问题的解如何合并
编码提示
•随机数生成
–srand(time(0));//设置随机数种子
•要#include <cstdlib>
–rand();//生成[0,MAX)之间的随机整数•要#include <cstdlib>
–for(int i=0;i<10;i++)
{
ran_num=rand() % 10;
cout<<ran_num<<" ";
}//生成不大于10的随机整数
编码提示
•最近点对问题的分治策略
–S:平面上的二维点集合
–预处理:分别根据点的x轴和y轴坐标进行排序,得到X和Y,很显然此时X和Y中的点就是S中的点
编码提示
•Conquer
–两个递归调用,分别求出S L和S R中的最短距离为d l 和d
r
编码提示
•Combine
–对于Y’L中的每一点,检查Y’R中的点与它的距离,更新所获得的最近距离。