分支限界法实现单源最短路径问题

合集下载

单元最短路径问题 分支限界法

单元最短路径问题 分支限界法

单元最短路径问题分支限界法【序】单元最短路径问题:分支限界法解析【引】在计算机科学中,图论问题一直是研究的热点之一。

而图的最短路径问题更是其中一个经典的困难问题。

在图中,单元最短路径问题就是要找到两个顶点之间的最短路径。

而在解决这个问题的过程中,我们可以借助分支限界法,来帮助我们找到最优的解。

本文将深度分析单元最短路径问题及分支限界法,以帮助读者全面理解并掌握这一问题解决方法。

【1】什么是单元最短路径问题?单元最短路径问题是图论中常见的一个问题,它要求在一个加权有向图或无向图中,找到两个给定顶点之间的最短路径。

该问题的解决方法包括了广度优先搜索、迪杰斯特拉算法等多种方法,其中分支限界法是一种常用的解决方法之一。

【2】分支限界法的基本思想分支限界法是一种通过搜索解空间来找到最优解的方法。

它通过将问题空间划分为一系列子问题,并不断搜索当前最优解的子空间,从而逐渐缩小问题空间,最终找到最优解。

【3】分支限界法在单元最短路径问题中的应用在解决单元最短路径问题时,分支限界法可以通过以下步骤来实施:1. 确定初始解和问题空间:选择一个顶点作为起始点,并设置一个初始解,例如将起始点的路径长度设置为0,其他顶点的路径长度设置为无穷大。

2. 扩展节点:从初始解开始,按照一定的扩展策略选择下一个节点进行扩展。

在单元最短路径问题中,我们可以选择将当前节点的邻接节点添加到解空间中。

3. 更新当前解:根据当前解空间中的节点,更新各节点的路径长度。

4. 剪枝:根据一定的条件,判断是否要剪去一些节点,从而缩小问题空间。

5. 重复上述步骤:不断迭代地重复上述步骤,直到找到最优解或者问题空间为空。

【4】为什么分支限界法适用于单元最短路径问题?分支限界法适用于单元最短路径问题的原因有以下几点:1. 分支限界法能够保证找到最优解。

通过不断地缩小问题空间,分支限界法能够找到最小的路径长度。

2. 分支限界法具有较高的搜索效率。

在每一步中,分支限界法都能够通过剪枝操作,排除一部分不可能达到最优解的节点,从而减少了搜索空间。

贪心算法和分支限界法解决单源最短路径

贪心算法和分支限界法解决单源最短路径

单源最短路径计科1班朱润华2012040732方法1:贪心算法一、贪心算法解决单源最短路径问题描述:单源最短路径描述:给定带权有向图G=(V,E),其中每条边的权是非负实数。

另外,还给定V中的一个顶点,称之为源(origin)。

现在要计算从源到其他各顶点的最短路径的长度。

这里的路径长度指的是到达路径各边权值之和。

Dijkstra算法是解决单源最短路径问题的贪心算法。

Dijkstra算法的基本思想是:设置顶点集合S并不断地做贪心选择来扩充集合。

一个顶点属于集合S当且仅当从源点到该顶点的最短路径长度已知。

贪心扩充就是不断在集合S中添加新的元素(顶点)。

初始时,集合S中仅含有源(origin)一个元素。

设curr是G的某个顶点,把从源到curr 且中间只经过集合S中顶点的路称之为从源到顶点curr的特殊路径,并且使用数组distance记录当前每个顶点所对应的最短路径的长度。

Dijkstra算法每次从图G中的(V-S)的集合中选取具有最短路径的顶点curr,并将curr加入到集合S中,同时对数组distance 进行必要的修改。

一旦S包含了所有的V中元素,distance数组就记录了从源(origin)到其他顶点的最短路径长度。

二、贪心算法思想步骤:Dijkstra算法可描述如下,其中输入带权有向图是G=(V,E),V={1,2,…,n},顶点v是源。

c是一个二维数组,c[i][j]表示边(i,j)的权。

当(i,j)不属于E时,c[i][j]是一个大数。

dist[i]表示当前从源到顶点i的最短特殊路径长度。

在Dijkstra算法中做贪心选择时,实际上是考虑当S添加u之后,可能出现一条到顶点的新的特殊路,如果这条新特殊路是先经过老的S到达顶点u,然后从u经过一条边直接到达顶点i,则这种路的最短长度是dist[u]+c[u][i]。

如果dist[u]+c[u][i]<dist[i],则需要更新dist[i]的值。

分支限界法实验(单源最短路径)

分支限界法实验(单源最短路径)

分⽀限界法实验(单源最短路径)算法分析与设计实验报告第七次实验基本思想:附录:完整代码(分⽀限界法)Shorest_path.cpp//单源最短路径问题分⽀限界法求解#include#include#include#include"MinHeap2.h"using namespace std;templateclass Graph //定义图类{friend int main();public:void shortest_path(int); private:int n, //图的顶点数*prev; //前驱顶点数组Type **c, //图的邻接矩阵*dist; //最短距离数组};templateclass MinHeapNode //最⼩堆中的元素类型为MinHeapNode{friend Graph;public:operator int() const{return length;}private:int i; //顶点编号Type length; //当前路长};//单源最短路径问题的优先队列式分⽀限界法templatevoid Graph::shortest_path(int v){MinHeap> H(1000);//定义最⼩堆的容量为1000//定义源为初始扩展结点MinHeapNode E;//初始化源结点E.i=v;E.length=0;dist[v]=0;while(true)//搜索问题的解空间{for(int j=1;j<=n;j++)if((c[E.i][j]!=0)&&(E.length+c[E.i][j]{//顶点i到顶点j可达,且满⾜控制约束//顶点i和j之间有边,且此路径⼩于原先从源点i到j的路径长度dist[j]=E.length+c[E.i][j];//更新dist数组prev[j]=E.i;//加⼊活结点优先队列MinHeapNode N;N.i=j;N.length=dist[j];H.Insert(N);//插⼊到最⼩堆中}try{H.DeleteMin(E); // 取下⼀扩展结点}catch (int){break;}if(H.currentsize==0)//优先队列空{break;}}}int main(){int n=11;int prev[12]={0,0,0,0,0,0,0,0,0,0,0,0};//初始化前驱顶点数组intdist[12]={1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000};//初始化最短距离数组cout<<"单源图的邻接矩阵如下:"<int **c=new int*[n+1];for(int i=1;i<=n;i++) //输⼊图的邻接矩阵{c[i]=new int[n+1];for(int j=1;j<=n;j++){cin>>c[i][j];}}int v=1; //源结点为1Graph G;G.n=n;G.c=c;G.dist=dist;G.prev=prev;clock_t start,end,over; //计算程序运⾏时间的算法start=clock();end=clock();over=end-start;start=clock();G.shortest_path(v);//调⽤图的最短路径查找算法//输出从源结点到⽬的结点的最短路径cout<<"从S到T的最短路长是:"<for(int i=2;i<=n;i++)//输出每个结点的前驱结点{cout<<"prev("<}for(int i=2;i<=n;i++) //输出从源结点到其他结点的最短路径长度{cout<<"从1到"<}for(int i=1;i<=n;i++) //删除动态分配时的内存{delete[] c[i];}delete[] c;c=0;end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显⽰运⾏时间cout< system("pause");return 0;}MinHeap.h#includetemplateclass Graph;templateclass MinHeap //最⼩堆类{templatefriend class Graph;public:MinHeap(int maxheapsize=10); //构造函数,堆的⼤⼩是10~MinHeap(){delete[] heap;} //最⼩堆的析构函数int Size() const{return currentsize;} //Size()返回最⼩堆的个数T Max(){if(currentsize) return heap[1];} //第⼀个元素出堆MinHeap& Insert(const T& x); //最⼩堆的插⼊函数MinHeap& DeleteMin(T& x); //最⼩堆的删除函数void Initialize(T x[],int size,int ArraySize); //堆的初始化void Deactivate();void output(T a[],int n);private:int currentsize,maxsize;T *heap;};templatevoid MinHeap::output(T a[],int n) //输出函数,输出a[]数组的元素{for(int i=1;i<=n;i++)cout<cout<}templateMinHeap::MinHeap(int maxheapsize){maxsize=maxheapsize;heap=new T[maxsize+1]; //创建堆currentsize=0;}templateMinHeap& MinHeap::Insert(const T& x){if(currentsize==maxsize) //如果堆中的元素已经等于堆的最⼤⼤⼩return *this; //那么不能在加⼊元素进⼊堆中int i= ++currentsize;while(i!=1 && x{heap[i]=heap[i/2];i/=2;}heap[i]=x;return *this;}templateMinHeap& MinHeap::DeleteMin(T& x) //删除堆顶元素{if(currentsize==0){cout<<"Empty heap!"<return *this;}x=heap[1];T y=heap[currentsize--];int i=1,ci=2;while(ci<=currentsize){if(ciheap[ci+1])ci++;if(y<=heap[ci])break;heap[i]=heap[ci];i=ci;ci*=2;}heap[i]=y;return *this;}templatevoid MinHeap::Initialize(T x[],int size,int ArraySize) //堆的初始化{ delete[] heap;heap=x;currentsize=size;maxsize=ArraySize;for(int i=currentsize/2;i>=1;i--){T y=heap[i];int c=2*i;while(c<=currentsize){if(cheap[c+1])c++;if(y<=heap[c])break;heap[c/2]=heap[c];c*=2;}heap[c/2]=y;}}templatevoid MinHeap::Deactivate() {heap=0;}。

分支限界法实现单源最短路径问题

分支限界法实现单源最短路径问题

实验五分支限界法实现单源最短路径一实验题目:分支限界法实现单源最短路径问题二实验要求:区分分支限界算法与回溯算法的区别,加深对分支限界法的理解。

三实验内容:解单源最短路径问题的优先队列式分支限界法用一极小堆来存储活结点表。

其优先级是结点所对应的当前路长。

算法从图G的源顶点s和空优先队列开始。

结点s被扩展后,它的儿子结点被依次插入堆中。

此后,算法从堆中取出具有最小当前路长的结点作为当前扩展结点,并依次检查与当前扩展结点相邻的所有顶点。

如果从当前扩展结点i到顶点j有边可达,且从源出发,途经顶点i再到顶点j的所相应的路径的长度小于当前最优路径长度,则将该顶点作为活结点插入到活结点优先队列中。

这个结点的扩展过程一直继续到活结点优先队列为空时为止。

四实验代码#include<iostream>using namespace std;const int size = 100;const int inf = 5000; //两点距离上界const int n = 6; //图顶点个数加1int prev[n]; //图的前驱顶点int dist[] = {0,0,5000,5000,5000,5000}; //最短距离数组int c[n][n] = {{0,0,0,0,0,0},{0,0,2,3,5000,5000}, //图的邻接矩阵 {0,5000,0,1,2,5000},{0,5000,5000,0,9,2},{0,5000,5000,5000,0,2},{0,5000,5000,5000,5000,0}};const int n = 5; //图顶点个数加1int prev[n]; //图的前驱顶点int dist[] = {0,0,5000,5000,5000};int c[][n] = {{0,0,0,0,0},{0,0,2,3,5000},{0,5000,0,1,2},{0,5000,5000,0,9},{0,5000,5000,5000,0}};class MinHeapNode{public :int i; //顶点编号int length; //当前路长};//循环队列class CirQueue{private:int front,rear;MinHeapNode data[size];public:CirQueue(){front = rear = 0;}//元素入队操作void queryIn(MinHeapNode e){if((rear +1)%size != front){rear = (rear+1)%size; //队尾指针在循环意义下加1 data[rear] = e; //在队尾插入元素}}//元素出队操作MinHeapNode queryOut(){if(rear != front){front = (front+1)%size; //队列在循环意义下加1 return data[front];}} //读取队头元素,但不出队MinHeapNode getQuery(){if(rear != front){return data[(front+1)%size];}} //判断队列是否为空bool empty(){return front == rear;} //判断队列是否为满bool full(){return (rear +1)%size == front;}};//CirQueue结束class Graph{public:/*** 单源最短路径问题的优先队列式分支限界法*/void shortestPath(int v){CirQueue qq;//定义源为初始扩展结点MinHeapNode e;e.i = v;e.length = 0;dist[v] = 0;qq.queryIn(e); //搜索问题的解空间while(true){for(int j = 1;j<n;j++){if(j>=n){break;}MinHeapNode m = qq.getQuery();if((c[m.i][j]<inf)&&(m.length + c[m.i][j] < dist[j])) {//顶点i到顶点j可达,且满足控制约束dist[j] = m.length + c[m.i][j];prev[j] = m.i;//加入活结点优先队列MinHeapNode mi;mi.i = j;mi.length = dist[j];if(qq.full()){break;}qq.queryIn(mi); //元素入队}}//for循环结束if(qq.empty()){break;}qq.queryOut(); //当该结点的孩子结点全部入队后,删除该结点 }//while循环结束}//方法结束};//类结束int main(){Graph g;g.shortestPath(1);cout<<"最短路径长为 "<<dist[n-1]<<endl; cout<<"中间路径为: ";for(int i =3;i<n;i++){cout<<prev[i]<<" ";}cout<<endl<<"欢迎使用本系统"<<endl;return 0;}五实验心得:通过实验,了解了分支限界法的基本思想。

用分支限界法求解单源最短路径问题

用分支限界法求解单源最短路径问题
添加到队列中。 重复以下步骤直到队列为空:

从队列中取出距离起始节点最近的节点作为当前节点。

对当前节点进行扩展操作,生成其可达的所有邻居节点。

对于每个邻居节点,计算通过当前节点到达该节点的距离,并更新
其距离值。

如果更新后的距离小于该节点当前的最短距离,则更新节点的最短
距离,并将其添加到队列中。
当队列为空时,所有节点的最短路径已经确定。 根据计算得到的最短距离,可以重构最短路径。从目标节点开始,按照每个 节点的最短路径前驱逐步回溯,直到回溯到起始节点,即可得到最短路径。
分支限界法 优化搜索过程。它通过限制搜索空间,避免了对所有可能路径进行穷举搜索,从 而提高了算法的效率。
需要注意的是,分支限界法的实现可能涉及具体的数据结构和算法细节,包 括如何表示图、选择优先队列的实现方式等。具体的实现方法可以根据实际情况 进行调整和优化。
分支限界法(Branch and Bound)是一种常用的算法策略,可用于解决单 源最短路径问题。下面是使用分支限界法求解单源最短路径问题的基本步骤:
初始化:将起始节点设置为当前节点,并将其到起始节点的距离设为 0。将
其他节点到起始节点的距离设为无穷大。 创建一个优先队列(通常使用最小堆)用于存储待扩展的节点。将起始节点

分支限界法实现单源最短路径

分支限界法实现单源最短路径

算法分析与设计实验报告分支限界法实现单源最短路径班级:11计算机1学号:110104200109姓名:金李扬日期: 5.221.问题描述以分支限界法实现单源最短路径1.以分支限界实现优先队列2.再以分支限界法的优先队列实现单元最短路径以该图为算法测试数据,获得链接矩阵如下:以-1代表无法到达的点-1 2 3 4 -1 -1 -1 -1 -1 -1 -1-1 -1 3 -1 7 2 -1 -1 -1 -1 -1-1 -1 -1 -1 -1 9 2 -1 -1 -1 -1-1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1-1 -1 -1 -1 -1 -1 -1 3 3 -1 -1-1 -1 -1 -1 -1 -1 1 -1 3 -1 -1-1 -1 -1 -1 -1 -1 -1 -1 5 1 -1-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 3-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 3-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -12.算法思想分支限界法基本思想:分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。

在分支限界法中,每一个活结点只有一次机会成为扩展结点。

活结点一旦成为扩展结点,就一次性产生其所有儿子结点。

在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。

此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。

这个过程一直持续到找到所需的解或活结点表为空时为止。

算法步骤1.用一极小堆来存储活结点表,其优先级是结点所对应的当前路长。

2.算法从图G的源顶点s和空优先队列开始。

结点s被扩展后,它的儿子结点被依次插入堆中。

此后,算法从堆中取出具有最小当前路长的结点作为当前扩展结点,并依次检查与当前扩展结点相邻的所有顶点。

分支限界法求解单源最短路径

分支限界法求解单源最短路径

一道难题:如何用分支限界法求解单源最短路径单源最短路径问题是图论中的经典问题之一,不仅在实际生活中有广泛应用,而且对于算法设计和分析也有重要价值。

分支限界法是一种解决最短路径问题的强有力工具。

在这篇文章中,我们将详细介绍如何用分支限界法求解单源最短路径问题。

首先,我们需要了解单源最短路径问题的定义。

给定一个有向图和一个起点s,对于图中的每一个顶点v,找到从s到v的最短路径。

这里的最短路径是指从s到v经过的边权之和最小的路径。

接下来,我们可以按照以下步骤实现用分支限界法求解单源最短路径问题:1. 初始化距离数组dist[],将s到其他所有点的距离设置为无穷大,将s到自己的距离设置为0。

2. 将起点s加入优先队列,队列中的元素按照距离dist[]从小到大排序。

3. 从优先队列中取出距离最小的顶点u,并遍历u的邻居节点v。

如果从s到v的距离可以通过从s到u再到v的路径更优,则更新dist[]数组和优先队列中的元素。

4. 重复步骤3,直到队列为空或者找到终点。

如果找到终点,则最优解就是dist[]数组中终点的值。

上述步骤中,第3步的优化是通过分支限界法实现的。

我们利用了贪心策略,并将目标函数设为从s到u的最短路径距离加上从u到v 的边权。

对于每一个节点u,我们只扩展目标函数值最小的那条边。

这样可以大幅度减少搜索空间,提高算法效率。

在实际应用中,分支限界法不仅可以求解单源最短路径问题,还可以应用于其他的组合优化问题中。

希望读者能够在掌握了基本理论和算法之后,加深对于分支限界法的理解,从而更好地解决实际问题。

分支限界法实验(单源最短路径)

分支限界法实验(单源最短路径)

算法分析与设计实验报告第七次实验姓名学号班级时间12.26上午地点工训楼309实验名称分支限界法实验(单源最短路径)实验目的1.掌握并运用分支限界法的基本思想2.运用分支限界法实现单源最短路径问题实验原理问题描述:在下图所给的有向图G中,每一边都有一个非负边权。

要求图G的从源顶点s 到目标顶点t之间的最短路径。

基本思想:下图是用优先队列式分支限界法解有向图G的单源最短路径问题产生的解空间树。

其中,每一个结点旁边的数字表示该结点所对应的当前路长。

为了加速搜索的进程,应采用有效地方式选择活结点进行扩展。

按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。

catch (int){break;}if(H.currentsize==0) //优先队列空{break;}}}上述有向图的结果:测试结果附录:完整代码(分支限界法)Shorest_path.cpp//单源最短路径问题分支限界法求解#include<iostream>#include<time.h>#include<iomanip>#include"MinHeap2.h"using namespace std;template<class Type>class Graph //定义图类{friend int main();public:void shortest_path(int); private:int n, //图的顶点数*prev; //前驱顶点数组Type **c, //图的邻接矩阵*dist; //最短距离数组};template<class Type>class MinHeapNode //最小堆中的元素类型为MinHeapNode{friend Graph<Type>;public:operator int() const{return length;}private:int i; //顶点编号Type length; //当前路长};//单源最短路径问题的优先队列式分支限界法template<class Type>void Graph<Type>::shortest_path(int v){MinHeap<MinHeapNode<Type>> H(1000);//定义最小堆的容量为1000//定义源为初始扩展结点MinHeapNode<Type> E;//初始化源结点E.i=v;E.length=0;dist[v]=0;while(true)//搜索问题的解空间{for(int j=1;j<=n;j++)if((c[E.i][j]!=0)&&(E.length+c[E.i][j]<dist[j])){//顶点i到顶点j可达,且满足控制约束//顶点i和j之间有边,且此路径小于原先从源点i到j的路径长度dist[j]=E.length+c[E.i][j];//更新dist数组prev[j]=E.i;//加入活结点优先队列MinHeapNode<Type> N;N.i=j;N.length=dist[j];H.Insert(N);//插入到最小堆中}try{H.DeleteMin(E); // 取下一扩展结点}catch (int){break;}if(H.currentsize==0)//优先队列空{break;}}}int main(){int n=11;int prev[12]={0,0,0,0,0,0,0,0,0,0,0,0};//初始化前驱顶点数组intdist[12]={1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000 };//初始化最短距离数组cout<<"单源图的邻接矩阵如下:"<<endl;int **c=new int*[n+1];for(int i=1;i<=n;i++) //输入图的邻接矩阵{c[i]=new int[n+1];for(int j=1;j<=n;j++){cin>>c[i][j];}}int v=1; //源结点为1Graph<int> G;G.n=n;G.c=c;G.dist=dist;G.prev=prev;clock_t start,end,over; //计算程序运行时间的算法start=clock();end=clock();over=end-start;start=clock();G.shortest_path(v);//调用图的最短路径查找算法//输出从源结点到目的结点的最短路径cout<<"从S到T的最短路长是:"<<dist[11]<<endl;for(int i=2;i<=n;i++)//输出每个结点的前驱结点{cout<<"prev("<<i<<")="<<prev[i]<<" "<<endl;}for(int i=2;i<=n;i++) //输出从源结点到其他结点的最短路径长度{cout<<"从1到"<<i<<"的最短路长是:"<<dist[i]<<endl;}for(int i=1;i<=n;i++) //删除动态分配时的内存{delete[] c[i];}delete[] c;c=0;end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显示运行时间cout<<endl;system("pause");return 0;}MinHeap.h#include<iostream>template<class Type>class Graph;template<class T>class MinHeap //最小堆类{template<class Type>friend class Graph;public:MinHeap(int maxheapsize=10); //构造函数,堆的大小是10~MinHeap(){delete[] heap;} //最小堆的析构函数int Size() const{return currentsize;} //Size()返回最小堆的个数T Max(){if(currentsize) return heap[1];} //第一个元素出堆MinHeap<T>& Insert(const T& x); //最小堆的插入函数MinHeap<T>& DeleteMin(T& x); //最小堆的删除函数void Initialize(T x[],int size,int ArraySize); //堆的初始化void Deactivate();void output(T a[],int n);private:int currentsize,maxsize;T *heap;};template<class T>void MinHeap<T>::output(T a[],int n) //输出函数,输出a[]数组的元素{for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<endl;}template<class T>MinHeap<T>::MinHeap(int maxheapsize){maxsize=maxheapsize;heap=new T[maxsize+1]; //创建堆currentsize=0;}template<class T>MinHeap<T>& MinHeap<T>::Insert(const T& x){if(currentsize==maxsize) //如果堆中的元素已经等于堆的最大大小return *this; //那么不能在加入元素进入堆中int i= ++currentsize;while(i!=1 && x<heap[i/2]){heap[i]=heap[i/2];i/=2;}heap[i]=x;return *this;}template<class T>MinHeap<T>& MinHeap<T>::DeleteMin(T& x) //删除堆顶元素{if(currentsize==0){cout<<"Empty heap!"<<endl;return *this;}x=heap[1];T y=heap[currentsize--];int i=1,ci=2;while(ci<=currentsize){if(ci<currentsize && heap[ci]>heap[ci+1])ci++;if(y<=heap[ci])break;heap[i]=heap[ci];i=ci;ci*=2;}heap[i]=y;return *this;}template<class T>void MinHeap<T>::Initialize(T x[],int size,int ArraySize) //堆的初始化{delete[] heap;heap=x;currentsize=size;maxsize=ArraySize;for(int i=currentsize/2;i>=1;i--){T y=heap[i];int c=2*i;while(c<=currentsize){if(c<currentsize && heap[c]>heap[c+1])c++;if(y<=heap[c])break;heap[c/2]=heap[c];c*=2;}heap[c/2]=y;}}template<class T>void MinHeap<T>::Deactivate(){heap=0; }。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验五分支限界法实现单源最短路径
一实验题目:分支限界法实现单源最短路径问题
二实验要求:区分分支限界算法与回溯算法的区别,加深对分支限界法的理解。

三实验内容:解单源最短路径问题的优先队列式分支限界法用一极小堆来存储活结点表。

其优先级是结点所对应的当前路长。

算法从图G的源顶点s和空优先队列开始。

结点s被扩展后,它的儿子结点被依次插入堆中。

此后,算法从堆中取出具有最小当前路长的结点作为当前扩展结点,并依次检查与当前扩展结点相邻的所有顶点。

如果从当前扩展结点i到顶点j有边可达,且从源出发,途经顶点i再到顶点j的所相应的路径的长度小于当前最优路径长度,则将该顶点作为活结点插入到活结点优先队列中。

这个结点的扩展过程一直继续到活结点优先队列为空时为止。

四实验代码
#include<iostream>
using namespace std;
const int size = 100;
const int inf = 5000; //两点距离上界
const int n = 6; //图顶点个数加1
int prev[n]; //图的前驱顶点
int dist[] = {0,0,5000,5000,5000,5000}; //最短距离数组
int c[n][n] = {{0,0,0,0,0,0},{0,0,2,3,5000,5000}, //图的邻接矩阵 {0,5000,0,1,2,5000},{0,5000,5000,0,9,2},
{0,5000,5000,5000,0,2},{0,5000,5000,5000,5000,0}};
const int n = 5; //图顶点个数加1
int prev[n]; //图的前驱顶点
int dist[] = {0,0,5000,5000,5000};
int c[][n] = {{0,0,0,0,0},{0,0,2,3,5000},{0,5000,0,1,2},{0,5000,5000,0,9},
{0,5000,5000,5000,0}};
class MinHeapNode
{
public :
int i; //顶点编号
int length; //当前路长
};//循环队列
class CirQueue{
private:
int front,rear;
MinHeapNode data[size];
public:
CirQueue(){
front = rear = 0;
}//元素入队操作
void queryIn(MinHeapNode e){
if((rear +1)%size != front){
rear = (rear+1)%size; //队尾指针在循环意义下加1 data[rear] = e; //在队尾插入元素
}
}//元素出队操作
MinHeapNode queryOut(){
if(rear != front){
front = (front+1)%size; //队列在循环意义下加1 return data[front];
}
} //读取队头元素,但不出队
MinHeapNode getQuery(){
if(rear != front)
{
return data[(front+1)%size];
}
} //判断队列是否为空
bool empty()
{
return front == rear;
} //判断队列是否为满
bool full()
{
return (rear +1)%size == front;
}
};//CirQueue结束
class Graph{
public:
/**
* 单源最短路径问题的优先队列式分支限界法
*/
void shortestPath(int v)
{
CirQueue qq;//定义源为初始扩展结点
MinHeapNode e;
e.i = v;
e.length = 0;
dist[v] = 0;
qq.queryIn(e); //搜索问题的解空间
while(true){
for(int j = 1;j<n;j++)
{
if(j>=n)
{
break;
}
MinHeapNode m = qq.getQuery();
if((c[m.i][j]<inf)&&(m.length + c[m.i][j] < dist[j])) {
//顶点i到顶点j可达,且满足控制约束
dist[j] = m.length + c[m.i][j];
prev[j] = m.i;
//加入活结点优先队列
MinHeapNode mi;
mi.i = j;
mi.length = dist[j];
if(qq.full()){
break;
}
qq.queryIn(mi); //元素入队
}
}//for循环结束
if(qq.empty())
{
break;
}
qq.queryOut(); //当该结点的孩子结点全部入队后,删除该结点 }//while循环结束
}//方法结束
};//类结束
int main(){
Graph g;
g.shortestPath(1);
cout<<"最短路径长为 "<<dist[n-1]<<endl; cout<<"中间路径为: ";
for(int i =3;i<n;i++){
cout<<prev[i]<<" ";
}
cout<<endl<<"欢迎使用本系统"<<endl;
return 0;
}
五实验心得:
通过实验,了解了分支限界法的基本思想。

知道了分支限界算法与回溯算法的区别。

相关文档
最新文档