最接近点对问题实验报告
最接近点对问题实验报告
最接近点对问题一.实验目的: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.数据存入文件:本次对文件的输入没有存入文本文件中,只将输出数据输入到指定的文件夹中,用到了输出流文件。
最近点对问题
最近点对问题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中的点。
如何写实验报告(共5篇)
篇一:怎么写生物实验报告实验报告一般分为以下几个部分:一、实验名称。
二、实验原理。
将该实验的主要原理用简明扼要的语言进行归纳总结。
三、实验仪器和材料。
如果所用仪器和材料较多,可写重要的部分,常用的可以不写。
四、实验步骤。
该实验如何操作的,方法和顺序。
可以用方框图表示,这样一目了然。
五、实验结果。
将该实验最后结果用文字或图表的方式进行表达。
推荐用表格或图进行表示。
要注意将度量单位写清楚。
六、实验讨论。
该部分主要对上述实验结果进行讨论。
有的是对实际操作中实验现象或结果和实验指导不一致的原因进行讨论,有的是对实际操作中产生的实验现象的原理或原因进行讨论,有的是对实际操作中可以改进的方法进行讨论,有的是对该实验的进一步应用进行讨论等等。
篇二:如何写实验报告如何写实验报告以书面形式交流你的研究结果是任何科学探索的必要组成部分。
除了书面交流外,常常还需要口头交流。
实验报告与正式发表研究论文的写作形式略有不同。
撰写实验报告是改善写作技巧,提高逻辑思维、分析思维和批判思维能力的非常有效的方式。
即使本课程的部分学生将来可能不从事科学研究工作,但是写作和思维技巧对任何行业都是重要的。
一个好的实验报告应是简洁的、组织良好的、有逻辑的和完整的。
图片已关闭显示,点此查看图片已关闭显示,点此查看图片已关闭显示,点此查看图片已关闭显示,点此查看图片已关闭显示,点此查看图片已关闭显示,点此查看实验报告写作应该遵循下面的格式,包括六个部分。
这与大部分用于发表的科研报告的格式大致相同,只是略有变化。
题目题目要简洁、清楚、切中主题。
题目占一行,位于中间。
在题目下面写出实验者姓名,实验内容的名称,实验时间,同组同学姓名。
同组同学可用一个报告题目。
引言本部分解释为什么做这个研究。
在引言中必须清楚的提出一个问题和陈述你要证实的假设。
通常从观察开始,发现问题,然后提出假设。
例如,你发现外面有的植物叶片变黄,你想知道是否影响光合作用。
你想用测定不同绿色叶片的叶绿素含量和光合速率的方法来检验你的想法。
全站仪点放样实验报告(5篇)
全站仪点放样实验报告(5篇)学生现在学习的内容是为以后的进展奠定根底,是丰富自己的文化学问,是自己能够成为一个对社会,对国家有用的人才,但是现在我们所学的学问大多只是理论上的东西,为此我们应当将理论和实际联系起来,积极参与实际工程,这次为期20天的实习教会了我们如何将自己所学的学问应用于实际工程工程之中,懂得了解决一些实际问题的k“ href=“/Special/xuexifangfa/“ target=“_blank“方法,对增加自己的生活和工作经受有很大益。
同时也可以说这次工作是对同学的一次考念,在实习过程中有的同学虽然生病但是依旧坚持工作,可以说着种精神是相当名贵的。
通过这次野外工程实习,加强了自身把握数字测图外业数据采集方法与内业作图方法,更加深刻的理解了数字测图在野外的运用,数字测图带来的不但是数据采集速度的提高,工作效率的增加,更加减轻了工作人员的工作强度;明白了在数据采集过程中应当留意的问题,使自己在课堂上学到的学问得到了在实际中的运首先,通过实习,让我发觉我在平常学习中存在的许多学问漏洞。
课本上介绍仪器使用的学问都比拟抽象,到了真正实践中的时候,我们未能很好把书本学问应用到实践中,还需要教师再次进展指导。
在近距离的接触这些实物,能我更坚固的把握相关的学问点;也能令我提高对仪器的操作的娴熟、精准程度(比方能够快速对中整平)。
全站仪点放样试验报告二首先感谢学校和教师给以了我这次参与工程实践的时机,在这次20多天的实习过程中,经过这次实习,无论在心理上还是在生理上都得到了很好的熬炼,全站仪测量实习报告。
学生现在学习的内容是为以后的进展奠定根底,是丰富自己的文化学问,是自己能够成为一个对社会,对国家有用的人才,但是现在我们所学的学问大多只是理论上的东西,为此我们应当将理论和实际联系起来,积极参与实际工程,这次为期20天的实习教会了我们如何将自己所学的学问应用于实际工程工程之中,懂得了解决一些实际问题的方法,对增加自己的生活和工作经受有很大好处,实习报告《全站仪测量实习报告》。
最近点对算法 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.实验总结:从本次试验中得到的领悟是:分治法事把问题分解成两个相似小问题,子问题和原来的大问题解决方法一样所以可以用递归,分治法重要是找到递归出口,什么时候递归结束,一般都有元素个数的限制。
算法——蛮力法之最近对问题和凸包问题
算法——蛮⼒法之最近对问题和凸包问题 上次的博客写到⼀半宿舍停电了。
然⽽今天想起来补充完的时候发现博客园并没有⾃动保存哦,微笑。
最近对问题 ⾸先来看最近对问题,最近对问题描述的就是在包含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代表的纵坐标,这样就可以直接创建该结构的⼀位数组进⾏计算了。
最近点对算法
最近点对算法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]内,查找可能的更近点对。
最近点对问题
算法分析与设计最近对问题最近对问题问题描述:在二维平面上的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)。
在这⾥介绍⼀种时间复杂度为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},如下图所⽰。
如果最接近点对是{q3,p3},即|p3-q3|<d,则p3和q3两者与m的距离都不超过d,且在区间(m-d,d]和(d,m+d]各有且仅有⼀个点。
这样,就可以在线性时间内实现合并。
此时,⼀维情形下的最近点对时间复杂度为O(nlogn)。
在⼆维情形下,类似的,利⽤分治法,但是难点在于如何实现线性的合并?由上图可见,形成的宽为2d的带状区间,最多可能有n个点,合并时间最坏情况下为n^2,。
但是,P1和P2中的点具有以下稀疏的性质,对于P1中的任意⼀点,P2中的点必定落在⼀个d X 2d的矩形中,且最多只需检查六个点(鸽巢原理)。
分治法解决空间最接近点对问题
第一作者简介 : 筱魁(90 , , 李 18 一)男 吉林省四平市人 , 为吉林师 范大学研究生部助教 , 现 硕士 . 研究方 向: 计算机视觉及 图形图像 .
论 最关 键 的问题 是 如 何 实 现分 治 法 中的合 并 步骤 ,
即由 . 和 . 的最接近点对 , s l s 2 如何求得原集合 . 中 s 的最 接近点 对 , 因为 J 和 J s 1 s 2的最 接 近点对 未 必 就 提法为 : 给定 平 面上 n个点 , 找其 中的 一对 点 , 得 使 是 . s的最接 近点对 . 如果 组 成 . s的最 接 近 点对 的 2 在 n 个点 的所 有点 对 中 , 该点 对 的距离 最小 ( 格 地 严 个 点 都在 . 中或都在 . 中 , s 1 s 2 只需 比较 一 次 即可 确 说, 最接 近点 对可 能 多于 一对 . 了简 单起 见 , 里 为 这 定; 但是 , 如果 这 2个点 分别 在 s 和 s 。 2中, 对 于 则 只限于找其 中的一对)朴素的解法只要将每一点与 . . 中任 一点 P, 2 s , S 中最 多只有 n 2 点 与它构成 最 /个 其 他 n一1 个点 的距 离算 出 , 出达 到最 小距离 的两 找 接近点对的候选者 , 仍需做 n/ 次计算和比较才能 4 个点即可 . 然而, 这样做效率太低 , 需要 0 n ) ( 的计 确定 .的最接近点对 , s 合并步骤耗时为 0 n )可 ( . 算 时间 , 分 治法可 以得 到 0( lg ) 用 no n 的算 法 l . 2 三 J 以看 出 , 并 步骤耗 时太 多 , 合 我们应 在合并 算法 上进 维 空间 中的最 接近点 对 问题 , 如 , 例 在空 中交通 控制 行 改进 . 我们 用 ( ) 示 P点 的 坐标 值 . P 表 首先 递 问题 中, 将飞 机作 为空间 中移 动 的一个 点来看 待 , 若 归地 在 . 和 . 上 解最 接 近点对 问题 , s l s 2 我们 分 别 得 则在任 一 时刻具 有 最大 碰撞 危 险 的二 架 飞 机 , 是 就 到 . s 1和 . s 2中 的 最 小 距 离 1 和 2 设 = .现 这个空 间 中最接 近 的一 对 点 , 其 求 解 的相 关 文 献 对 mn l )若 S的最接 近点对 ( q i( , . 2 P, )之 间的距 离 非常少 , 本文把用分治法解决平 面最接近点对问题 d q P)< , P和 q必分 属 于 . 和 . . (, 则 s l s 不妨设 P 2 推广 到三维 空 间 中. ∈S, lq∈ S , 么 , 2那 P和q 平面 Z 距 的距 离均小 于 . 2 算法实现 因此 , 我们 若用 P1 P2 别 表示平 面 Z 后 的宽 和 分 前 为 的 2 区域 ( . 个 P 为平 面 = / 与平 面 = / + / 7 , / 7 , 空 间最接 近点 对问题 描 述 : 定 含 有 n个 空 间 给 P2 / 7 , 点 的集 合 ., 出其 中一对点 , 得在 由这 n个 点 构 之 间所 夹的 区域 , 为平 面 = / 与平 面 = n s找 使
报告最接近点对问题
实验报告—最接近点对问题1、问题描述:给定n个点(xi,yi) 1<=i<=n,找出其中距离最近的两个点。
分析:采用分而治之设计技术,将平面上的n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近点。
于是,原问题变为:(1)求S1中最近距离的两个点;(2)求S2中最近距离的两个点;(3)由(1)、(2)得到S中的最接近点。
有一个关键:如何实现组合解?(1)如果组成S中的最近距离点都在S1中,或都在S2中,则问题很容易解决!(2)如果组成S中的最近距离点分别在S1和S2中,那么,如何组合解?由鸽舍原理对于P1中任一点p,P2中最多只有6个点与它构成最近点的侯选者,于是组合解只需要检查6*(n/2)=3n对侯选点而不是n(2)/4个。
将p和P2中的所有S2的点投影到垂直线l上,由于能与p点构成侯选点的点都在矩形R中,所以它们在直线l上的投影点距p在l上的投影点的距离都小于最近距离。
从上面的分析知,这种点只有6个。
因此,若将P1和P2中的所有点按其y坐标排好序,则对P1中的所有点,对排好序的所有点作一次扫描,就可以找出所有最接近点对的侯选者,对P1中的每一点最多只要检查P2中排好序的相继的6个点。
2、基本算法:Public static double cpair2(S){如果点的个数n小于2,则显示提示信息:只有一个点不能求距离,终止算法;1.m=S中各点x坐标的中位数;(S为点的集合)构造S1和S2;//S1={p∈S|x(p)<=m}, S2={p∈S|x(p)>m}2. d1=cpair2(S1); d2=cpair2(S2);3. dm=min(d1,d2);4. 设P1是S1中距垂直分割线l的距离在dm之内的所有点组成的集合;设P2是S2中距垂直分割线l的距离在dm之内的所有点组成的集合;将P1和P2中点依其y坐标值排序,并设X和Y是相应的已排好序的点列;5.通过扫描X以及对于X中每个点检查Y中与其距离在dm之内的所有点(最多6个).当X中的扫描指针逐次向上移动时,Y中的扫描指针可在宽为2dm的区间内移动;设dl是按这种扫描方式找到的点对间的最小距离;6.d=min(dm,dl);Return d;}3、实现环境和运行平台:采用java编写程序,jdk4.0编译调试,使用jdk的appletviewer显示运行结果。
分治法实现最接近点对问题的三维推广算法
某 个 {,q} P ,, 点对 的距 离 , 中 P 其 ∈S ,,∈S. .q !如
图 1 示: 所
范 围的点 构成 的两个垂 直 长条 平 面 区域 , . { ∈ P :P
20 0 6正
二 维情况 中 , . s中的每个 点 都 有 和 Y两 个 坐 标. 选取 一垂 直线 L: =m( m为 . s中各 点 坐标 的 中 位数 ) 为分 割直线 , . 割 为 . 和 . 两个 半 作 将s 分 s s 平 面区域 中点 的子集 , 归地 在 . 递 s . 分别 找 和 s 上
{ lq } 并设 d =mi l l 2 , l—q }S q ,2 , n{ P —P I I q 2 . I
中 的最接 近 点 对 或 者 是 {。P } 或 者是 {。q } P ,: , q ,: ,
一
●
或者是某个 {,q}其 中一定有 P ∈ ( — , P ,, , , m dm l
一
O 引言
在计算 机应 用 中 , 用 点 、 常 圆等 简 单 的几 何 对 象表 达现 实世 界 中的实体 涉及 这些几 何对 象 的 在 问题 中 , 需 要 了解 其 领 域 中其 他 几 何 对 象 的信 常 息. 接近 点对 问题 常用 于空 中交通 的计 算机 自动 最 控制 系统 中. 是计 算机 几何 学研 究 的基 本 问题之 也
—
维情况下 , s中的 n 个点退化为数轴上的 n
个实数点 ,: . , 最接近的点对即为这n 。 … . . 个
最接近点对问题算法
最接近点对问题算法
最接近点对问题是指在平面上给定N个点,找出其中距离最
近的两个点的距离。
可以使用以下算法来解决最接近点对问题:
1. 将所有点按照水平或垂直坐标排序,以便可以更方便地进行后续操作。
2. 将所有点分为两个大致相等的集合,分别称为左集合和右集合。
3. 递归地在左集合和右集合中找出最小距离的点对。
4. 取两个集合中最小距离的点对中较小的距离minDistance。
5. 在以水平坐标为准的线段中,确认是否存在两个点,它们的横坐标之差小于minDistance,并计算它们的距离。
6. 在以垂直坐标为准的线段中,确认是否存在两个点,它们的纵坐标之差小于minDistance,并计算它们的距离。
7. 取步骤5和步骤6中距离的最小值,记为delta。
8. 在左集合和右集合中,找出间距水平线的范围内的点,并按照纵坐标排序。
9. 使用二重循环,依次计算两个集合中的相邻点对之间的距离,直到纵坐标的差大于等于delta。
10. 比较得到的距离和minDistance,取较小的值作为最终的最小距离。
以上算法的时间复杂度为O(nlogn),其中n为点的数量。
最接近点对问题
.
11
能否在线性时间内找到p3,q3
❖ 第一步筛选:如果最近点对由S1中的p3和 S2中的q3组成,则p3和q3一定在划分线L 的距离d内。
需要计算P1中的每个点与. P2中的每个点的距离? 12
并不必计算P1中的每个点与P2中的每个点的距离!O(n2)
❖ 第二步筛选:考虑P1中任意一点p,它若与 P2中的点q构成最接近点对的候选者,则必 有distance(p,q)<d。满足这个条件的P2 中的点一定落在一个d×2d的矩形R中
点,则此点就是S2中最小点。
因此,我们用线性时间就能找到区间(m-d,m]和(m,m+d]中所
有点,即p3和q3。从而我们用线性时间就可以将S1的解和S2的
解合并成为S的解。
.
9
❖ public static double Cpair1(S,d) //找S中最接近点对的距离d
❖{
❖ n=|S|; //S中点的个数
若矩形R中有多于6个S中的 点,则由鸽舍原理易知至少有 一个(d/2)×(2d/3)的小矩形中 有2个以上S中的点。
设u,v是位于同一小矩形中 的2个点,则
(x(u) x(v))2 ( y(u) y(v))2 (d / 2)2 (2d / 3)2 25 d 2
distance(u,v)<d。这与d的. 意义相矛盾。 36 15
distance ( u, v)
(x(u) x(v))2 ( y(u) y(v))2 (z(u) z(v))2 (d / 2)2 (d / 2)2 (2d / 3)2 17 d 2 18
distance(u,v)<d。这与d的. 意义相矛盾。
23
报告最接近点对问题
报告最接近点对问题实验报告—最接近点对问题1、问题描述:给定n个点(xi,yi) 1<=i<=n,找出其中距离最近的两个点。
分析:采用分而治之设计技术,将平面上的n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近点。
于是,原问题变为:(1)求S1中最近距离的两个点;(2)求S2中最近距离的两个点;(3)由(1)、(2)得到S中的最接近点。
有一个关键:如何实现组合解?(1)如果组成S中的最近距离点都在S1中,或都在S2中,则问题很容易解决!(2)如果组成S中的最近距离点分别在S1和S2中,那么,如何组合解?由鸽舍原理对于P1中任一点p,P2中最多只有6个点与它构成最近点的侯选者,于是组合解只需要检查6*(n/2)=3n对侯选点而不是n(2)/4个。
将p和P2中的所有S2的点投影到垂直线l上,由于能与p点构成侯选点的点都在矩形R中,所以它们在直线l上的投影点距p在l上的投影点的距离都小于最近距离。
从上面的分析知,这种点只有6个。
因此,若将P1和P2中的所有点按其y坐标排好序,则对P1中的所有点,对排好序的所有点作一次扫描,就可以找出所有最接近点对的侯选者,对P1中的每一点最多只要检查P2中排好序的相继的6个点。
2、基本算法:Public static double cpair2(S){如果点的个数n小于2,则显示提示信息:只有一个点不能求距离,终止算法;1.m=S中各点x坐标的中位数;(S为点的集合) 构造S1和S2;//S1={p∈S|x(p)<=m}, S2={p∈S|x(p)>m}2. d1=cpair2(S1); d2=cpair2(S2);3. dm=min(d1,d2);4. 设P1是S1中距垂直分割线l的距离在dm之内的所有点组成的集合;设P2是S2中距垂直分割线l的距离在dm之内的所有点组成的集合;将P1和P2中点依其y坐标值排序,并设X和Y是相应的已排好序的点列;5.通过扫描X以及对于X中每个点检查Y中与其距离在dm之内的所有点(最多6个).当X中的扫描指针逐次向上移动时,Y中的扫描指针可在宽为2dm的区间内移动;设dl是按这种扫描方式找到的点对间的最小距离;6.d=min(dm,dl);Return d;}3、实现环境和运行平台:采用java编写程序,jdk4.0编译调试,使用jdk的appletviewer显示运行结果。
三区划线实验报告
三区划线实验报告自从和大家在一起玩,对我有了很大的触动。
这个小区我看到了很多的问题,我想了很久,没有找到一个很好的解决办法。
就只能看着我们的孩子一点点成长。
我有一次给他写了一篇文章《孩子写作业时:我们应该怎样陪孩子》,得到了家长的共鸣。
而在我们小区里发现有不少家长和我一样,对于自己正在做的事情都不是那么喜欢和了解,所以我希望能够引起大家的共鸣。
一、为什么要做这次实验?当看到这些消息的时候,我就开始着手想这些问题,我们小区里的一些居民,他们的反应,有多少是和我一样呢?在他们眼里的世界就是如此的美好。
而当看到其他人都在忙碌着作业,我们也在忙于写作业。
看着家长和自己一样忙碌着,却不知这一切是多么得不公平地。
因为他没有时间。
我希望他们能够在这个时间和你们在一起,并且用游戏来做些什么让你们有所改变和成长。
我们一起来看看有多少不被理解的吧!也许在你需要的时候,这些不被你需要的地方是你生活中最容易忽略、最需要解决的问题了。
就像之前让我写文章一样,只是为了看你而已!1、我和妈妈都要加班,可是我只有一小时的时间。
我们是一个家庭,而不仅仅是一个班级,有太多的时间都浪费在了孩子身上。
每天上学的路上,妈妈和老师经常打电话和发信息,却总是说没有空子可钻。
我很讨厌父母给我太多的时间让我忙。
妈妈总是要接电话,而我们总是说我们要有一个更长的时间学习。
你有一小时的时间吗?2、由于家长都很忙,所以他们需要一个可以和他们沟通的时间。
所以,我希望能够在这个时间和他们聊天和做一些关于教育的事情。
而不是一味地去要求他们为自己做什么,而忽略他对你来说有着怎样的意义。
我希望可以改变这些不被理解的东西,让他们有所改变!所以这次我决定要做这次实验!3、对于教师来说,他们要面对的是一个优秀的学生,所以我选择用游戏这种方式来让他们和我一起做一个实验。
这一点让我对这些孩子们很有信心。
因为我知道你们有自己的时间,我会和你们共同努力,把这个三区划线做得更好。
点云对齐——精选推荐
点云对齐杨成林∗2009年5月31日进行数据采集时,由于受到测量设备和坏境的限制,物体表面完整测量数据的获得往往需要通过多次测量完成。
由于每次测量得到的点云数据往往只覆盖物体部分表面,并且可能出现平移错位和旋转错位,因此为了得到物体完整表面的点云数据,需要对这些局部点云数据进行对齐。
点云的对齐所用的方法可分为两种,一种是依靠测量设备进行对齐,另一种则是根据测量后的数据处理对齐。
第一种方法通过特定的设备测量待测工件或测量传感器在多次测量中的位姿。
通过测得的位姿来对齐多次测量数据。
这一方法快速方便,不需后续处理,不过需要额外的设备,而且不能完全满足测量视角的要求。
第二种方法利用测量得到的数据进行对齐,不受设备的约束,测量视角的选择可以更加自由,不过有时计算量很大,而且会因为局部最优等问题得不到正确的对齐。
本文主要讨论后一种对齐方式。
1ICP方法对于两个点集:作为对齐基准的点集P={p1,p2,...,p n}和待对齐的点集X={x1,x2,...,x m},两个点云的对齐是使以下目标函数的值最小f(R,t)=mi=1||Rx i+t−y i||22(1)其中R和t分别是旋转矩阵和平移向量,而y i是点x i经过变换后的对应点。
此公式中,对应点可以有多种定义方法,比如规定y i为点x i在P中的最近点。
点云对齐问题的难点在于:y i是R和t的函数,事先无法确定,而∗*****************1且对应点的求取通常是计算量很大的工作。
在对应点是最近点的情况,原始的方法计算复杂度为O(mn),常用的改进方法kd-tree方法计算复杂度在最好的情况下为O(m log n)。
在点集中点数很多的情况下,计算上的消耗是很大的,所以目标函数求值是计算量很大的工作。
虽然对于一般的最优化问题,减少目标函数的计算次数也是一个重要的目标,但在点云对齐问题中,减少目标函数的计算显得尤为重要。
为了解决这一问题,对齐问题的处理通常分为初始对齐和精确对齐两步。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最接近点对问题
一.实验目的:
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);//合并到数组a
Copy(a,b,left,right);//复制回数组a
}
}
3.数据存入文件:
本次对文件的输入没有存入文本文件中,只将输出数据输入到指定的文件夹中,用到了输出流文件。
代码实现:
ofstream outFile;
outFile.open("E://程序设计/practice 1/算法设计与分析/文本文
件夹/最接近点对问题结果.txt",ios::trunc);
int length;
cout<<"请输入点对数:";
cin>>length;
xPosition X[M];
cout<<"随机生成的二维点对为:"<<endl;
outFile<<"随机生成的二维点对为:\n";
for(int i=0;i<length;i++){
X[i].ID=i;
X[i].x=Random();
X[i].y=Random();
cout<<"("<<X[i].x<<","<<X[i].y<<") ";
outFile<<"("<<X[i].x<<","<<X[i].y<<") \n";
}
xPosition a;
xPosition b;
float d;
start=clock();
Cpair2(X,length,a,b,d);
finish=clock();
cout<<endl;
cout<<"最邻近点对为:("<<a.x<<","<<a.y<<")和
("<<b.x<<","<<b.y<<") "<<endl;
outFile<<"最邻近点对为:("<<a.x<<","<<a.y<<")和
("<<b.x<<","<<b.y<<") \n";
cout<<"最邻近距离为: "<<d<<endl;
outFile<<"最邻近距离为: "<<d<<"\n";
cout<<"程序运行时间:"<<finish-start<<endl;
outFile<<"程序运行时间:"<<finish-start;
outFile.close();
4.求解最短距离:
将总的点对分为三部分,对每一部分求解最短的距离,对只有两对、三对的情况直接进行距离求解。
当对每一部分求解最短距离时,采用分治法分解为一个个小的子问题,
对点在两个区域的情况,依照思想,进行排序比较,和已有的最短距离比较,最终确定最短距离的点对。
代码实现:
void closest(xPosition X[],yPosition Y[],yPosition Z[],int
left,int right,xPosition& a,xPosition& b,float& d){
if(right-left==1) //两点的情形
{
a=X[left];
b=X[right];
d=dis(X[left],X[right]);
return;
}
if(right-left==2) //3点的情形
{
float d1=dis(X[left],X[left+1]);
float d2=dis(X[left+1],X[right]);
float d3=dis(X[left],X[right]);
if(d1<=d2 && d1<=d3){
a=X[left];
b=X[left+1];
d=d1;
return;
}
if(d2<=d3){
a=X[left+1];
b=X[right];
d=d2;
}
else{
a=X[left];
b=X[right];
d=d3;
}
return;
}
//多于3点的情形,用分治法
int m=(left+right)/2;
int f=left,g=m+1;
for(int i=left;i<=right;i++){
if(Y[i].p>m) Z[g++]=Y[i];
else Z[f++]=Y[i];
}
closest(X,Z,Y,left,m,a,b,d);
float dr;
xPosition ar,br;
closest(X,Z,Y,m+1,right,ar,br,dr);
{
a=ar;
b=br;
d=dr;
}
Merge(Z,Y,left,m,right);//重构数组Y
int k=left;
for(int i=left;i<=right;i++){
if(fabs(X[m].x-Y[i].x)<d){
Z[k++]=Y[i];
}
}
//搜索Z[l:k-1]
for(int i=left;i<k;i++){
for(int j=i+1;j<k && Z[j].y-Z[i].y<d;j++){
float dp=dis(Z[i],Z[j]);
if(dp<d){
d=dp;
a=X[Z[i].p];
b=X[Z[j].p];
}
}
}
}
四.实验数据分析:
本实验对不同规模的数据进行测试,实验数据如下。
五.实验感受:
在实验中,随机生成一定数量的点对,对这些点对进行最短距离求解,由于设置的范围过小,在进行时间测量时,得到的数据都为零,故在进行实际分析时,需要使用大规模的数据。