算法实验二 分治法 最近点对问题

合集下载

最近点问题(分治法)

最近点问题(分治法)
for(int i=p;i<=q;i++)
{
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实现

⽤分治法解决最近点对问题: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、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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中的点与它的距离,更新所获得的最近距离。

相关文档
最新文档