蛮力法分治法求最近对
算法设计与分析-第3章-蛮力法
哨兵
0123456789 k 10 15 24 6 12 35 40 98 55
查找方向
i
清华大学出版社
算法设计与分析
算法3.2——改进的顺序查找
int SeqSearch2(int r[ ], int n, int k) //数组r[1] ~ r[n]存放查找集合 { r[0]=k; i=n; while (r[i]!=k)
清华大学出版社
算法设计与分析
第3章 蛮力法
3.1 蛮力法的设计思想 3.2 查找问题中的蛮力法 3.3 排序问题中的蛮力法 3.4 组合问题中的蛮力法 3.5 图问题中的蛮力法 3.6 几何问题中的蛮力法 3.7 实验项目——串匹配问题
清华大学出版社
算法设计与分析
3.1 蛮力法的设计思想
蛮力法的设计思想:直接基于问题的描述。 例:计算an
52 37 65 不可行 不可行 不可行 不可行 不可行
清华大学出版社
算法设计与分析
对于一个具有n个元素的集合,其子集 数量是2n,所以,不论生成子集的算法 效率有多高,蛮力法都会导致一个Ω(2n) 的算法。
清华大学出版社
算法设计与分析
3.4.4 任务分配问题
假设有n个任务需要分配给n个人执行, 每个任务只分配给一个人,每个人只分配一 个任务,且第j个任务分配给第i个人的成本 是C[i, j](1≤i , j≤n),任务分配问题要求 找出总成本最小的分配方案。
用蛮力法解决0/1背包问题,需要考虑给定n个 物品集合的所有子集,找出所有可能的子集(总重 量不超过背包容量的子集),计算每个子集的总价 值,然后在他们中找到价值最大的子集。
清华大学出版社
算法设计与分析
10
1007分治法(最近点对)
由此可得:
C11 C12 C 21 C 22
A11 B11 A12 B21 A11 B12 A12 B22 A21 B11 A22 B21 A21 B12 A22 B22
Strassen矩阵乘法
(1 ) C12 A11 AO B11 B12 n 2 C11 T ( 12 n) 2 C 7 T ( n / 2 ) O ( n ) n2 C A A B B 22 22 21 22 21 21 M 1 A11 ( B12 B22 ) T(n)=O(nlog7) =O(n2.81)较大的改进 C11 M 5 M 4 M 2 M 6 M 2 ( A11 A12 ) B22
规模较小的情况
n=2
规模较小的情况
n=4
规模较小的情况
n=4
规模较小的情况
n=8
规模较小的情况
n=8
规模较大的情况
当k>0时,将2k×2k棋盘分割为4个2k-1×2k-1 子棋盘(a)所示。 特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特 殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘, 可以用一个L型骨牌覆盖这3个较小棋盘的会合处,如 (b)所 示,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归 地使用这种分割,直至棋盘简化为棋盘1×1。
Strassen矩阵乘法
传统方法:O(n3)
A和B的乘积矩阵C中的元素C[i,j]定义为:C[i][ j ] A[i][ k ]B[k ][ j ]
k 1 n
若依此定义来计算A和B的乘积矩阵C,则每计 算C的一个元素C[i][j],需要做n次乘法和n-1次 加法。因此,算出矩阵C的 个元素所需的计算 时间为O(n3)
蛮力法、分治法、减治法三种方法的理解和处理问题的类型的归纳
蛮力法、分治法、减治法三种方法的理解和处理问题的类型的归纳一、蛮力法蛮力法是一种基础且直接的问题解决策略,通常用于寻找问题的答案或解决方案。
其核心理念在于,通过逐一检查所有可能的解决方案,从而找到问题的答案或找到最佳的解决方案。
在蛮力法中,我们通常需要投入较多的时间和计算资源,尤其是在面对大规模或复杂的问题时。
蛮力法的应用范围广泛,包括但不限于以下几种类型的问题:1. 排序问题:例如,对一个数组进行排序,我们可以使用蛮力法,通过比较每对元素并交换它们的位置,使得整个数组有序。
2. 查找问题:例如,在排序数组中查找一个特定的元素,我们可以使用蛮力法,逐一检查数组中的每个元素直到找到目标元素。
3. 组合与排列问题:例如,计算给定集合的所有可能排列或组合,我们可以使用蛮力法,通过逐一排列或组合所有可能的元素组合得到答案。
二、分治法分治法是一种将复杂问题分解为更小、更易于处理的子问题的方法。
通过将问题分解为独立的子问题,我们可以分别解决每个子问题,然后将这些解决方案组合起来,形成原始问题的解决方案。
这种方法在处理复杂问题时非常有效,因为它可以降低问题的复杂性,使我们可以更有效地解决问题。
分治法的应用范围广泛,包括但不限于以下几种类型的问题:1. 排序问题:例如,归并排序就是一种使用分治法的排序算法,它将一个大列表分解为两个小列表,对这两个小列表分别进行排序,然后合并它们以得到有序列表。
2. 搜索问题:例如,二分搜索是一种使用分治法的搜索算法,它将搜索空间一分为二,每次迭代都排除一半的元素,直到找到目标元素或确定元素不存在。
3. 图问题:例如,Dijkstra的算法就是一种使用分治法的图搜索算法,它将图分解为最短路径树,然后通过搜索每个子图的最短路径来解决整个图的最短路径问题。
三、减治法减治法是一种通过减少问题的规模或复杂性来解决问题的方法。
其核心理念在于,通过消除或减少问题的某些部分或特性,从而降低问题的复杂性或规模,使得问题更容易解决。
最近点对问题
最近点对问题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.实验总结:从本次试验中得到的领悟是:分治法事把问题分解成两个相似小问题,子问题和原来的大问题解决方法一样所以可以用递归,分治法重要是找到递归出口,什么时候递归结束,一般都有元素个数的限制。
算法——蛮力法之最近对问题和凸包问题
算法——蛮⼒法之最近对问题和凸包问题 上次的博客写到⼀半宿舍停电了。
然⽽今天想起来补充完的时候发现博客园并没有⾃动保存哦,微笑。
最近对问题 ⾸先来看最近对问题,最近对问题描述的就是在包含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代表的纵坐标,这样就可以直接创建该结构的⼀位数组进⾏计算了。
最近点对问题
算法分析与设计最近对问题最近对问题问题描述:在二维平面上的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 中。
平面最近点对问题(分治)
平⾯最近点对问题(分治)平⾯最近点对问题是指:在给出的同⼀个平⾯内的所有点的坐标,然后找出这些点中最近的两个点的距离.⽅法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},如下图所⽰。
求两组点之间的最近点对实验总结
求两组点之间的最近点对实验总结在计算几何学和算法设计中,求两组点之间的最近点对是一个重要且常见的问题。
在这篇文章中,我将从简到繁地探讨这个主题,深入分析求解最近点对的算法,并进行实验总结,以便读者能更深入地理解这一概念。
一、什么是最近点对问题?最近点对问题是指在一个平面上给定n个点,要求在这些点中找到距离最近的两个点。
这个问题在实际中有着广泛的应用,比如计算机视觉中的物体识别、无人驾驶车辆的障碍物检测等都涉及到最近点对的计算。
设计高效的算法来解决最近点对问题具有重要意义。
二、最近点对的暴力解法最简单的方法是通过遍历所有点对,计算它们之间的距离,并找到最小值。
这种暴力解法的时间复杂度为O(n^2),空间复杂度为O(1),虽然简单易懂,但对于大规模的数据集来说效率较低。
三、分治法解决最近点对问题分治法是解决最近点对问题的常见方法,其基本思想是将点集分成两个子集,分别求解最近点对,然后再找出整个点集的最近点对。
在这个过程中需要用到分治、筛选和合并三个步骤。
具体算法流程如下:1. 将点集按照x坐标排序,找到中间线将点集分成左右两个子集。
2. 递归求解左右子集的最近点对。
3. 筛选出距离中线距离小于当前最近距离的点,将它们按照y坐标排序。
4. 在筛选后的点集中,以每个点为中心,向上下各取6个点。
5. 计算这些点之间的距离,更新最近距离。
6. 合并左右子集的结果,得到最终的最近点对。
使用分治法解决最近点对问题的时间复杂度为O(nlogn),效率较高,适用于大规模数据集。
四、实验总结及个人观点在进行最近点对的实验过程中,我发现分治法在处理大规模数据集时具有明显的优势,其算法设计合理、程序实现简单高效。
对于中等规模的数据集,暴力解法也能够得到较好的结果,但对于大规模数据集来说效率明显低于分治法。
我个人认为在解决最近点对问题时,应优先考虑使用分治法,并且可以根据数据规模选择不同的算法来达到更高的效率。
总结来说,求两组点之间的最近点对是一个重要且常见的问题,在实际应用中具有广泛的意义。
第三章 蛮力法PPT课件
个定值。设此值为SN ,则不难解
出:SN = N 2 ·(N 2 +1)/2N= N ·(N 2 +1) /2。
.
19
外延法(由巴谢提出)构造奇阶幻方
.
20
H·Coxeter构造幻方的方法
首先在正方形最上面一 行的正中间的小方格内 填写1,然后到它的左 上方的小格内填写下一 个数(注意:我们认为正 方形的同一行或同一行 的头尾是相连的)。如果 走到某个小方格,而该 格已填了数,那末就改 走到原方格的下面一个 方格。
axbyc13穷举查找14穷举查找15穷举查找分配问题n个任务分配给n个人任务j分配给人i的成本是cij16小结蛮力法是一种简单直接地解决问题的方法通常直接基于问题的描述和所涉及的概念定义
算法分析与设计
Analysis and Design of Computer Algorithms
第三章 蛮力法 Brute Force
.
21
习题3.4-10
.
22
直线方程:ax+by=c a=y2-y1 , b=x1-x2, c=x1y2-y1x2
.
12
旅行商问题
穷举查找
.
13
背包问题
穷举查找
.
14
穷举查找
分配问题
N个任务分配给n个人,任务j分配给人i的成本是C[I,j]
.
15
小结
蛮力法是一种简单直接地解决问题的方法,通常 直接基于问题的描述和所涉及的概念定义。
算法 解决问题的实例很少时,它让你花费较少的代
价 可以解决一些小规模的问题 可以作为其他高效算法的衡量标准
.
3
教学内容
第4章 蛮力法
for (i=0;i<n;i++)
//两重循环穷举所有的连续子序列
{ for (j=i;j<n;j++) { thisSum=0; for (k=i;k<=j;k++) thisSum+=a[k]; if (thisSum>maxSum) //通过比较求最大连续子序列之和 maxSum=thisSum; }
第4章 蛮力法
4.1 蛮力法概述 4.2 蛮力法的基本应用 4.3 递归在蛮力法中的应用
4.1 蛮力法概述
• 蛮力法也称穷举法,枚举法,暴力法,是一种简单直接地 解决问题的方法,是算法中最常用的方法之一
• 通常直接基于问题的描述和所涉及的概念定义,找出所有 可能的解。然后选择其中的一种或多种解,若该解不可行 则试探下一种可能的解。
//进行n-1趟排序
{
} }
exchange=false;
//本趟排序前置exchange为false
for (j=n-1;j>i;j--)
//无序区元素比较,找出最小元素
if (a[j]<a[j-1])
//当相邻元素反序时
{ swap(a[j],a[j-1]); //a[j]与a[j-1]进行交换
for (m=2;m<=1000;m++) { 求出m的所有因子之和s;
if (m==s) 输出s; }
对应的程序如下:
void main() { int m,i,s;
for (m=2;m<=1000;m++) { s=0;
for (i=1;i<=m/2;i++) if (m%i==0) s+=i; //i是m的一个因子
【分治法】最接近点对问题(转)
【分治法】最接近点对问题(转)转⾃:/liufeng_king/article/details/8484284问题场景:在应⽤中,常⽤诸如点、圆等简单的⼏何对象代表现实世界中的实体。
在涉及这些⼏何对象的问题中,常需要了解其邻域中其他⼏何对象的信息。
例如,在空中交通控制问题中,若将飞机作为空间中移动的⼀个点来看待,则具有最⼤碰撞危险的2架飞机,就是这个空间中最接近的⼀对点。
这类问题是计算⼏何学中研究的基本问题之⼀。
问题描述:给定平⾯上n个点,找其中的⼀对点,使得在n个点的所有点对中,该点对的距离最⼩。
严格地说,最接近点对可能多于1对。
为了简单起见,这⾥只限于找其中的⼀对。
1、⼀维最接近点对问题算法思路:这个问题很容易理解,似乎也不难解决。
我们只要将每⼀点与其他n-1个点的距离算出,找出达到最⼩距离的两个点即可。
然⽽,这样做效率太低,需要O(n^2)的计算时间。
在问题的计算复杂性中我们可以看到,该问题的计算时间下界为Ω(nlogn)。
这个下界引导我们去找问题的⼀个θ(nlogn)算法。
采⽤分治法思想,考虑将所给的n个点的集合S分成2个⼦集S1和S2,每个⼦集中约有n/2个点,然后在每个⼦集中递归地求其最接近的点对。
在这⾥,⼀个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对,因为S1和S2的最接近点对未必就是S的最接近点对。
如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。
但是,如果这2个点分别在S1和S2中,则对于S1中任⼀点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需做n^2/4次计算和⽐较才能确定S的最接近点对。
因此,依此思路,合并步骤耗时为O(n^2)。
整个算法所需计算时间T(n)应满⾜: T(n)=2T(n/2)+O(n^2)。
它的解为T(n)=O(n^2),即与合并步骤的耗时同阶,这不⽐⽤穷举的⽅法好。
蛮力法
算法设计2: 在公鸡(x)、母鸡(y)的数量确定后,小 鸡 的数量 z就固定为100-x-y,无需再进行枚举了 此时约束条件只有一个:5*x+3*y+z/3=100 算法2如下:
8
Z能被3整除时,才会判断“5*x+3*y+z/3=100
main( ) 枚举尝试20*33=660次 { int x,y,z; for(x=1;x<=20;x=x+1) for(y=1;y<=33;y=y+1) { z=100-x-y; if(z%3==0&&5*x+3*y+z/3==100) { print("the cock number is",x);
蛮力字符串匹配:即朴素模式串匹配
4
蛮力法解题步骤
根据问题中的条件将可能的情况一一列举出 来,逐一尝试从中找出满足问题条件的解。但有 时一一列举出的情况数目很大,如果超过了我们 所能忍受的范围,则需要进一步考虑,排除一些 明显不合理的情况,尽可能减少问题可能解的列 举数目。 用蛮力法解决问题,通常可以从两个方面进行算 法设计:
16
1)找出枚举范围:分析问题所涉及的各种情况。
2)找出约束条件:分析问题的解需要满足的条件,并用 逻辑表达式表示。
5
例1 百钱百鸡问题。中国古代数学家张丘建在他的 《算经》中提出了著名的“百钱百鸡问题”:鸡翁一, 值钱五;鸡母一,值钱三;鸡雏三,值钱一;百钱买 百鸡,翁、母、雏各几何?
算法设计1:
通过对问题的理解,可能会想到列出两个三元一次方程, 去解这个不定解方程,就能找出问题的解。这确实是一种 办法,但这里我们要用“懒惰”的枚举策略进行算法设计: 设x,y,z分别为公鸡、母鸡、小鸡的数量。
蛮力法详解
算法3.1——顺序查找
int SeqSearch1(int r[ ], int n, int k) //数组r[1] ~ r[n]存放查找集合
{ i=n;
基本语句 ?
while (i>0 && r[i]!=k)
i--;
return i;
}
算法3.1的基本语句是i>0和r[i]!=k,其执行次数为:
n
2020/6/14
Chapter 3 Brute force method
教学要求 理解 掌握
√
√ √ √
√ √ √
熟练掌握 √ √
√
4
3.1 概述:蛮力法的设计思想
蛮力法中“力”是指计算机的“计算能 力”,不是人的智“力”。
蛮力法的设计思想:直接基于问题的描述, 从有限集合中,逐一列举集合的所有元素, 对每一个元素逐一判断和处理,从而找出 问题的解。
如已知:公钥为:KU={e, n},私钥为: KR={d, n},则 对明文m的加密/解密算法如下:
加密 明文: M<n 密文: C=Me (mod n)
密文: 明文:
解密 C M=Cd (mod n)
注:计算an算法的效率直接影响到RSA算法的性能
2020/6/14
Chapter 3 Brute force method
2020/6/14
Chapter 3 Brute force method
7
蛮力法的设计思想
因要穷举待处理的元素,故蛮力法的时间性能往往最低, 但基于以下原因,蛮力法也是一种重要的算法设计技术:
(1)理论上,蛮力法可以解决可计算领域的各种问题。 (2)蛮力法经常用来解决一些较小规模的问题。 (3)对于一些重要的问题(例如排序、查找等)蛮力法 可以产生一些合理的算法,他们具备一些实用价值,而且 不受问题规模的限制。 (4)蛮力法可以作为某类问题时间性能(不是复杂性, 两者恰好相反)的下界,来衡量同样问题的更高效算法。
算法设计与分析习题答案1
算法设计与分析习题答案1算法设计与分析习题答案1习题1 1. 图论诞生于七桥问题。
出生于瑞士的伟大数学家欧拉提出并解决了该问题。
七桥问题是这样描述的:北区一个人是否能在一次步行中穿越哥尼斯堡城中全部岛区的七座桥后回到起点,且每座桥只经过一次,南区图是这条河以及河上的两个岛和七座桥的图七桥问题草图。
请将该问题的数据模型抽象出来,并判断此问题是否有解。
七桥问题属于一笔画问题。
输入:一个起点输出:相同的点1,一次步行2,经过七座桥,且每次只经历过一次3,回到起点该问题无解:能一笔画的图形只有两类:一类是所有的点都是偶点。
另一类是只有二个奇点的图形。
2.在欧几里德提出的欧几里德算法中用的不是除法而是减法。
请用伪代码描述这个版本的欧几里德算法=m-n 2.循环直到r=0 m=n n=r r=m-n 3 输出m 3.设计算法求数组中相差最小的两个元素的差。
要求分别给出伪代码和C++描述。
//采用分治法//对数组先进行快速排序//在依次比较相邻的差#include using namespace std; int partions(int b,int low,int high) { int prvotkey=b[low]; b[0]=b[low]; while (low while (low=prvotkey)--high; b[low]=b[high]; while (low b[high]=b[low]; } b[low]=b[0]; return low; } void qsort(int l,int low,int high) { int prvotloc; if(low prvotloc=partions(l,low,high);//将第一次排序的结果作为枢轴qsort(l,low,prvotloc-1); //递归调用排序low 到prvotloc-1 qsort(l,prvotloc+1,high); //递归调用排序prvotloc+1到high } } void quicksort(int l,int n) { qsort(l,1,n); // 第一个作为枢轴,从第一个排到第n个} int main() { int a[11]={0,2,32,43,23,45,36,57,14,27,39};int value=0;//将最小差的值赋值给value for (int b=1;b quicksort(a,11); for(int i=0;i!=9;++i) { if( (a[i+1]-a[i]) value=a[i+2]-a[i+1]; } cout return 0; } 4.设数组a[n]中的元素均不相等,设计算法找出a[n]中一个既不是最大也不是最小的元素,并说明最坏情况下的比较次数。
蛮力法的实验报告
一、实验目的1. 理解蛮力法的基本概念和原理。
2. 掌握蛮力法的实现步骤。
3. 通过具体实例,验证蛮力法在解决实际问题中的效果和局限性。
二、实验原理蛮力法,也称为穷举法或枚举法,是一种直接基于问题描述的简单解决方法。
其基本思想是通过遍历所有可能的解空间,从中找出可行解,进而得到问题的最优解。
蛮力法的解题步骤如下:1. 找出解空间:确定问题可能的所有解的范围。
2. 遍历解空间:按照一定的顺序,逐一尝试所有可能的解。
3. 找出可行解:对每个解进行判断,确定其是否满足问题的约束条件。
4. 选取最优解:从所有可行解中,根据问题要求选择最优解。
三、实验内容本实验以“求一个三位数,个位数字比百位数字大,百位数字又比十位数字大,且各位数字之和等于各位数字相乘之积”的问题为例,采用蛮力法进行求解。
1. 解空间该问题的解空间为三位数,即100-999之间的所有整数。
2. 遍历解空间按照从100到999的顺序,逐一检查每个数是否满足以下条件:(1)个位数字比百位数字大;(2)百位数字比十位数字大;(3)各位数字之和等于各位数字相乘之积。
3. 找出可行解在遍历过程中,对于每个数,首先判断其是否为三位数。
如果是,再分别取出其百位、十位和个位数字,并判断是否满足上述条件。
4. 选取最优解由于该问题没有明确要求求解最优解,因此只需找出所有满足条件的解即可。
四、实验步骤1. 编写程序,实现蛮力法求解上述问题。
2. 运行程序,观察结果。
五、实验结果与分析1. 实验结果经过计算,发现满足条件的三位数有以下几个:- 145(1+4+5=10,1×4×5=20,不满足条件)- 261(2+6+1=9,2×6×1=12,不满足条件)- 352(3+5+2=10,3×5×2=30,不满足条件)- 463(4+6+3=13,4×6×3=72,不满足条件)- 514(5+1+4=10,5×1×4=20,不满足条件)- 625(6+2+5=13,6×2×5=60,不满足条件)- 736(7+3+6=16,7×3×6=126,不满足条件)- 847(8+4+7=19,8×4×7=224,不满足条件)- 959(9+5+9=23,9×5×9=405,不满足条件)2. 实验分析(1)蛮力法能够找到所有满足条件的解,但效率较低。
蛮力法
蛮力法
设计与开发大赛
一、蛮力法概述
蛮力法(也叫穷举法、暴力法)它 要求设计者找出所有可能的方法,然后 选择其中的一种方法,若该方法不可行 则试探下一种可能的方法。 显然蛮力法(也叫穷举法)不是一 个最好的算法选择,但当我们想不出别 的更好的办法时,它也是一种有效的解 决问题的方法。
2
14
常州大学信息学院
设计与开发大赛
蛮力法的一般模式
1、问题解的可能搜索范围: 用循环或循环嵌套结构实现。 2、写出符合问题解的条件: 用条件语句实现判断。 3、对程序做一些优化,以便 缩小搜索范围,减少程序运行时间。
15
常州大学信息学院
设计与开发大赛
四、蛮力法练习
练习 1:36块砖,36个人搬。男搬 4,女搬3,两个小儿抬一砖。要求 一次搬完。问需男、女、小儿个若 干(必须都有)? 类似问题:一张100元,换成20, 10,5,1面值的零钞,每种至少一 张,共有哪些换法?总计多少种换 法?
设计与开发大赛
for(i=1;A<=5;i=i+1) { G2=G1; E1=E1/10; G1=E1%10; if(G1<>G2) break; } If(i==6) printf(“%d*%d=%d”F,A,E); }
12
常州大学信息学院
设计与开发大赛
算法优化:将算式由乘变为除。 算法优化 DDDDDD/A = ABCAB 尝试范围:3≤A≤9;1≤D≤9; 尝试范围 约束条件:每次除法所得的商的万 约束条件 位、十位与除数相同,商的千位与 个位相同。
8
常州大学信息学院
设计与开发大赛
例 2:编写算法解如下数字迷。 A B C A B × A D D D D D D
求最小差的方法
求最小差的方法
在现代科学中,人们经常遇到找出两个值之间的最小差的任务。
最小差的求解是重要的任务,它可以用在各种行业和领域,如统计分析、数据挖掘、计算机视觉等等,让我们看看求最小差的方法有哪些:(一)暴力求解法。
暴力求解法原理很简单,就是把所有可能的最小差组合都列出来,比较它们的大小,最后取出最小的那个。
这种方法很简单,但是它的运算量会非常大,特别是当数据量很大的时候,效率会下降。
(二)分治法。
分治法的思想是把一个大的问题划分成几个小的子问题,然后逐步解决,最终达到求解最小差的目的。
它可以把一个规模为n的问题划分为两个规模为n的子问题,然后再分别求解,最后再合并即可。
(三)动态规划法。
动态规划是一种利用子问题的重叠性来减少运算次数的方法,它让求解最小差更加有效。
它的基本思想是利用重叠性来减少比较次数,把给定的序列分割成若干小的子序列,比较他们之间的差值,最后得出最小差。
(四)贪心算法。
贪心算法是指在求解最小差的问题中,让每次操作获得最优解,最终得出总体最优解的一种方法。
贪心算法的核心思想是每次在相邻的两个数中求解最小差,获取最小差的累计。
以上是求最小差的几种方法,每种方法在处理求最小差的问题时都有自己的优势,我们可以根据自己的实际需要来选择合适的方法。
比如,如果数据量不大,可以采用暴力求解法,如果数据量较大,可
以采用分治法和动态规划法,如果要求计算效率,可以采用贪心算法。
总之,求最小差的方法有很多,我们需要根据实际的需求仔细研究各个方法的优缺点,然后选择最合适的一种方法来解决问题。
只有这样,才能在数据分析和处理中发挥更好的作用,提高计算效率。
点集直径问题算法
点集直径问题是指给定一组点,求出这组点中任意两点之间距离的最大值。
以下是解决点集直径问题的几种常见算法:
1.蛮力法:通过计算所有点对之间的距离,找到最大的距离。
时间复杂度为O(n^2),其中n是点
的数量。
这种方法简单但效率不高,特别是对于较大的点集。
2.分治法:该方法将点集分成两个子集,分别计算子集的直径,然后找到子集之间距离的最大值。
这个过程递归进行,直到子集的点数足够小,可以直接用蛮力法计算直径。
分治法的平均时间复杂度为O(nlogn),但最坏情况下可能达到O(n^2)。
3.基于哈希表的方法:该方法使用哈希表来存储每个点作为中心点时,其他点到该点的距离。
然后,
对于每个点,检查哈希表中是否存在其他点,其到当前点的距离大于当前的最大距离。
这种方法的时间复杂度为O(n^2),但常数因子较小,因此对于较小的点集可能比蛮力法更快。
4.优先队列法:该方法使用优先队列来存储距离最大的点对。
每次迭代时,从队列中删除最小距离
的点对,并计算新点对的距离。
如果新距离大于当前最大距离,则更新最大距离和队列。
这种方法的时间复杂度为O(nlogn)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验题目设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。
实验目的(1)进一步掌握递归算法的设计思想以及递归程序的调试技术;(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。
实验内容(包括代码和对应的执行结果截图)#include<iostream>#include<cmath>#include <windows.h>using namespace std;typedef struct Node{//定义一个点的结构,用于表示一个点int x;int y;}Node;typedef struct NList{//定义一个表示点的集合的结构Node* data;int count;}NList;typedef struct CloseNode{//用于保存最近两个点以及这两个点之间的距离Node a;Node b;double space;}CloseNode;int max;void create(NList & L){cout<<"请输入平面上点的数目:\n";cin>>max;L.count=max;L.data = new Node[L.count];//====================动态空间分配cout<<"输入"<<L.count<<"个点坐标X,Y,以空格隔开:"<<endl;for(int i=0;i<L.count;i++)cin>>L.data[i].x>>L.data[i].y;}//求距离平方的函数double Distinguish2(Node a,Node b){return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));}//蛮力法求最近对void BruteForce(const NList & L,CloseNode & cnode,int begin,int end){for(int i=begin;i<=end;i++)for(int j=i+1;j<=end;j++){double space = Distinguish2(L.data[i],L.data[j]);if(space<cnode.space){cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}}//归并排序void Merge(Node SR[],Node TR[],int i,int m,int n){//将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]int j,k;for(j=m+1,k=i;i<=m&&j<=n;k++)if(SR[i].x<=SR[j].x) TR[k]=SR[i++];else TR[k]=SR[j++];while(i<=m) TR[k++]=SR[i++];while(j<=n) TR[k++]=SR[j++];}void Msort(Node SR[],Node TR1[],int s,int t){//将SR[s..t]归并排序为TR1[s..t]if(s==t) TR1[s]=SR[s];else{int m = (s+t)/2;Node *TR2=new Node[max];//new Node[t-s+1];//这个空间挂挂的,从s到t,这里是从0到t-sMsort(SR,TR2,s,m);Msort(SR,TR2,m+1,t);Merge(TR2,TR1,s,m,t);}}void MergeSort(NList L){Msort(L.data,L.data,0,L.count-1);}//分治法求最近对中间2d对称区的算法void Middle(const NList & L,CloseNode & cnode,int mid,int midX){int i,j;int d = sqrt(cnode.space);i=mid;while(i>=0&&L.data[i].x>=(midX-d)){j=mid;while(L.data[++j].x<=(midX+d)&&j<=L.count){//1,j++ 2<=,>=if(L.data[j].y<(L.data[i].y-d)||L.data[j].y>(L.data[i].y+d))continue;double space = Distinguish2(L.data[i],L.data[j]);if(cnode.space>space){cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}i--;}}// ----------------------------------------------//分治法求最近对void DivideAndConquer(const NList &L,CloseNode & closenode,int begin,int end) {if((end-begin+1)<4) BruteForce(L,closenode,begin,end);else{int mid = (begin+end)/2;int midX = L.data[mid].x;DivideAndConquer(L,closenode,begin,mid);DivideAndConquer(L,closenode,mid+1,end);Middle(L,closenode,mid,midX);}}int main(){SYSTEMTIME sys;GetLocalTime( &sys );NList list;CloseNode closenode;closenode.space = 10000;create(list);cout<<"各点坐标为:"<<endl;for(int i=0;i<list.count;i++)cout<<"X="<<list.data[i].x<<" Y="<<list.data[i].y<<"\n";BruteForce(list,closenode,0,list.count-1);cout<<"用蛮力法求最近对:"<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;cout<<"==================================================== ================"<<endl;cout<<"用分治法求最近对:"<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;MergeSort(list);cout<<"经过归并排序后的各点:"<<endl;for(int j=0;j<list.count;++j)cout<<"X="<<list.data[j].x<<" Y="<<list.data[j].y<<"\n";DivideAndConquer(list,closenode,0,list.count-1);cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;return 0;}实验结果分析由以上数据可知,分治法效率比蛮力法效率高。
蛮力法求解最近对问题的过程是:分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计算两次距离,只考虑i <j 的那些点对(Pi , Pj )。