蛮力法分治法求最近对

合集下载

分治法和蛮力法求解最近对问题

分治法和蛮力法求解最近对问题

蛮力法与分治法求解最近对问题摘要:在计算机科学理论和程序设计实践中,往往会面对众多的问题,面对这些问题,人们想到了很多算法来解决。

最常见也最常用的是蛮力法,在解决问题和研究算法过程中,人们常在不断探索和寻求许多好的算法来求解同一个问题。

本文就最近对问题,分别对蛮力法和分治法的思想、复杂度、效率做了一定的讲述,并对两个方法在此问题中的效率进行了简单分析。

关键字:蛮力法、分治法、效率。

一.引言通常我们所说的最接近对问题是指平面上(即二维坐标平面)给定n 个点,找其中的一对点,使得在n 个点的所有点对中,,该点对的距离最小。

在求解这个问题时,我们可以采用很多算法来实现。

最朴素的解法就是蛮力法,所谓蛮力法就是将是一种简单直接地解决问题的方法,常常直接基于问题的描述和所涉及的概念定义,来求解问题。

这样一来,显得蛮力法确实比较实用而方便。

往往事物都有两面性,此算法确实简单实用,可是效率却比较低。

所以我们针对不同问题时,要采用合适的算法来求解,达到效率和求解难度综合起来达到一个比较好的极点。

本文在研究最近对问题时又采用了分治法,所谓分治法,就是分而治之即把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题直到问题解决。

本文只是针对一个比较简单的问题最近对问题采用两个不同算法求解进行分析解剖。

二.算法概述及实用范围2.1、蛮力法蛮力法是一种简单直接地解决问题的方法,常常直接基于问题的描述和所涉及的概念定义,来求解问题。

虽然巧妙和高效的算法很少来自于蛮力法,但它仍是一种重要的算法设计策略:(1)适用泛围广,是能解决几乎所有问题的一般性方法;(2)常用于一些非常基本、但又十分重要的算法(排序、查找、矩阵乘法和字符串匹配等);(3)解决一些规模小或价值低的问题;(4)可以做为同样问题的更高效算法的一个标准;(5)可以通过对蛮力法的改进来得到更好的算法。

2、分治法分治法,就是分而治之即把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题直到问题解决。

算法设计与分析-第3章-蛮力法

算法设计与分析-第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分治法(最近点对)

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中的点。

实验项目1:蛮力法与分治法应用

实验项目1:蛮力法与分治法应用

实验项目1:蛮力法与分治法应用1、目的与要求:实验目的:了解蛮力法和分治法的基本思想,学会运用蛮力法和分治法解决实际系统设计应用中碰到的问题。

实验要求:用蛮力法实现选择、冒泡排序,或旅行商问题、背包问题等问题(任选其中之一)。

用分治法实现合并排序或快速排序。

要求写出算法的伪代码描述,并编写程序实现之,相关算法放在函数实现,主程序给出测试用例,要设计足够多的相关测试用例,验证程序的正确性。

注意观察程序执行结果和运行的时间。

实验报告要求给出问题定义及算法的伪代码描述,程序设计的代码,算法的测试用例及结果,并分析算法的时间效率,回答指导书中的思考题。

2、实验容:(2)用分治法实现快速排序、合并排序算法。

本实验主要是用分治法实现合并排序,快速排序程序等。

合并排序算法描述:MergeSort ( A[0...p-1] )// input 待排序数组A[0..n-1]// output 非降序排列的数组A[0..n-1]if ( n>1 ) {//至少有2个元素Copy A[0.. n/2-1 ] to B[0.. n/2-1 ];Copy A[n/2..n-1 ] to C[0.. n/2-1 ];MergeSort ( B[0.. n/2-1 ] );MergeSort (C[0.. n/2-1 ]t);Merge (B, C, A); //复制回数组a快速排序算法描述:QuickSort ( A[1.. r ] ){if (l<r) s=Partition( A[l,r] ); // s 是分裂位置QuickSort ( A[l..s-1] ); //对左半段排序QuickSort ( A[s+1,r); //对右半段排序}Partition ( A[l..r] ){p=A[[l] ;i = l; j = r + 1;repeatedrepeated i=i+1; until A[i]> p // 将>= x的元素交换到左边区域repeated i=i+1; until A[i]> p // <= x的元素交换到右边区域Swap( A[i], A[j] )Until i>jSwap( A[i] = a[j] );Swap( A[l], A[j] )return j;要求先给出算法的伪代码,然后用C++或其他程序设计语言编写程序实现之,并设计相关的测试用例,验证程序的正确性。

蛮力法、动态规划法、回溯法和分支限界法求解01背包问题【精选】

蛮力法、动态规划法、回溯法和分支限界法求解01背包问题【精选】

一、实验内容:分别用蛮力法、动态规划法、回溯法和分支限界法求解0/1背包问题。

注:0/1背包问题:给定种物品和一个容量为的背包,物品的重n C i 量是,其价值为,背包问题是如何使选择装入背包内的物品,使得装i w i v 入背包中的物品的总价值最大。

其中,每种物品只有全部装入背包或不装入背包两种选择。

二、所用算法的基本思想及复杂度分析:1.蛮力法求解0/1背包问题:1)基本思想:对于有n 种可选物品的0/1背包问题,其解空间由长度为n 的0-1向量组成,可用子集数表示。

在搜索解空间树时,深度优先遍历,搜索每一个结点,无论是否可能产生最优解,都遍历至叶子结点,记录每次得到的装入总价值,然后记录遍历过的最大价值。

2)代码:#include<iostream>#include<algorithm>using namespace std;#define N 100//最多可能物体数struct goods //物品结构体{int sign;//物品序号int w;//物品重量int p;//物品价值}a[N];bool m(goods a,goods b){return (a.p/a.w)>(b.p/b.w);}int max(int a,int b){return a<b?b:a;}int n,C,bestP=0,cp=0,cw=0;int X[N],cx[N];/*蛮力法求解0/1背包问题*/int Force(int i){if(i>n-1){if(bestP<cp&&cw+a[i].w<=C){for (int k=0;k<n;k++)X[k]=cx[k];//存储最优路径bestP=cp;}return bestP;}cw=cw+a[i].w;cp=cp+a[i].p;cx[i]=1;//装入背包Force(i+1);cw=cw-a[i].w;cp=cp-a[i].p;cx[i]=0;//不装入背包Force(i+1);return bestP;}int KnapSack1(int n,goods a[],int C,int x[]){Force(0);return bestP;}int main(){goods b[N];printf("物品种数n: ");scanf("%d",&n);//输入物品种数printf("背包容量C: ");scanf("%d",&C);//输入背包容量for (int i=0;i<n;i++)//输入物品i 的重量w 及其价值v {printf("物品%d 的重量w[%d]及其价值v[%d]:",i+1,i+1,i+1);scanf("%d%d",&a[i].w,&a[i].p);b[i]=a[i];}int sum1=KnapSack1(n,a,C,X);//调用蛮力法求0/1背包问题printf("蛮力法求解0/1背包问题:\nX=[ ");for(i=0;i<n;i++)cout<<X[i]<<" ";//输出所求X[n]矩阵printf("]装入总价值%d\n",sum1);bestP=0,cp=0,cw=0;//恢复初始化}3)复杂度分析:蛮力法求解0/1背包问题的时间复杂度为:。

算法——蛮力法之最近对问题和凸包问题

算法——蛮力法之最近对问题和凸包问题

算法——蛮⼒法之最近对问题和凸包问题 上次的博客写到⼀半宿舍停电了。

然⽽今天想起来补充完的时候发现博客园并没有⾃动保存哦,微笑。

最近对问题 ⾸先来看最近对问题,最近对问题描述的就是在包含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. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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 )。

相关文档
最新文档