贪心算法和分支限界法解决单源最短路径Word格式.docx
《贪心算法和分支限界法解决单源最短路径Word格式.docx》由会员分享,可在线阅读,更多相关《贪心算法和分支限界法解决单源最短路径Word格式.docx(11页珍藏版)》请在冰豆网上搜索。
![贪心算法和分支限界法解决单源最短路径Word格式.docx](https://file1.bdocx.com/fileroot1/2022-11/17/51e54d59-449f-4636-b582-d93d3c100f4e/51e54d59-449f-4636-b582-d93d3c100f4e1.gif)
dist[i]表示当前从源到顶点i的最短特殊路径长度。
在Dijkstra算法中做贪心选择时,实际上是考虑当S添加u之后,可能出现一条到顶点的新的特殊路,如果这条新特殊路是先经过老的S
如果dist[u]+c[u][i]<
dist[i],则需要更新dist[i]的值。
步骤如下:
1、用带权的邻接矩阵c来表示带权有向图,c[i][j]表示弧<
vi,vj>
上的权值。
设S为已知最短路径的终点的集合,它的初始状态为空集。
从源点v经过S到图上其余各点vi的当前最短路径长度的初值为:
dist[i]=c[v][i],vi属于V;
2、选择vu,使得dist[u]=Min{dist[i]|vi属于V-S},vj就是长度最短的最短路径的终点。
令S=SU{u};
3、修改从v到集合V-S上任一顶点vi的当前最短路径长度:
如果dist[u]+c[u][j]<
dist[j]则修改dist[j]=dist[u]+c[u][j];
4、重复操作
(2),(3)共n-1次。
三、算法实现代码:
#include<
stdafx.h>
iostream>
fstream>
string>
usingnamespacestd;
constintN=5;
constintM=1000;
ifstreamfin("
4d5.txt"
);
template<
classType>
voidDijkstra(intn,intv,Typedist[],intprev[],Typec[][N+1]);
voidTraceback(intv,inti,intprev[]);
//输出最短路径v源点,i终点intmain()
{
intv=1;
//源点为1
intdist[N+1],prev[N+1],c[N+1][N+1];
cout<
<
"
有向图权的矩阵为:
"
endl;
for(inti=1;
i<
=N;
i++)
for(intj=1;
j<
j++)
fin>
>
c[i][j];
c[i][j]<
;
}
Dijkstra(N,v,dist,prev,c);
for(inti=2;
源点1到点"
i<
的最短路径长度为:
dist[i]<
,其路径为"
Traceback(1,i,prev);
return0;
voidDijkstra(intn,intv,Typedist[],intprev[],Typec[][N+1])
bools[N+1];
=n;
dist[i]=c[v][i];
//dist[i]表示当前从源到顶点i的最短特殊路径长度
s[i]=false;
if(dist[i]==M)
prev[i]=0;
//记录从源到顶点i的最短路径i的前一个顶点
else
prev[i]=v;
dist[v]=0;
s[v]=true;
n;
inttemp=M;
intu=v;
//上一顶点
//取出V-S中具有最短特殊路径长度的顶点u
if((!
s[j])&
&
(dist[j]<
temp))
u=j
temp=dist[j];
s[u]=true;
//根据作出的贪心选择更新Dist值
(c[u][j]<
M))
Typenewdist=dist[u]+c[u][j];
if(newdist<
dist[j])
dist[j]=newdist;
prev[j]=u;
//输出最短路径v源点,i终点voidTraceback(intv,inti,intprev[])
if(v==i)
i;
return;
Traceback(v,prev[i],prev);
->
I;
四、计算复杂性
对于一个具有n个顶点和e条边的带权有向图,如果用带权邻接矩阵表示这个图,那
么Dijkstra算法的主循环体需要O(n)时间。
这个循环需要执行n-1次,所以完成循环需要
0(nA2)时间。
算法的其余部分所需要的时间不超过0(n^2)。
五、运行结果:
间图权的矩阵为’
1010S030100leaa
1B00
4
-
为为为为苴八苴苴八苴八
0000
1536
为为为为丽庫<
■度度0S8・
E0
0・
1-日一一口里□兰口“一
00曰W-W-1-取续
10的的的暑2345^L至至至至化朋畫巔昴按原原冃
・:
至至
11
1BB8
方法2:
分支限界法
一、分支限界法解决单源最短路径问题描述:
采用广度优先产生状态空间树的结点,并使用剪枝函数的方法称为分枝限界法。
所谓“分
支”是采用广度优先的策略,依次生成扩展结点的所有分支(即:
儿子结点)。
所谓“限界”
是在结点扩展过程中,计算结点的上界(或下界),边搜索边减掉搜索树的某些分支,从而
提高搜索效率
按照广度优先的原则,一个活结点一旦成为扩展结点(E-结点)R后,算法将依次生成
它的全部孩子结点,将那些导致不可行解或导致非最优解的儿子舍弃,其余儿子加入活结点
表中。
然后,从活结点表中取出一个结点作为当前扩展结点。
重复上述结点扩展过程,直至
找到问题的解或判定无解为止。
二、分支限界法算法思想描述:
算法从图G的源顶点s和空优先队列开始。
结点s被扩展后,它的儿子结点被依次插当前扩展结点相邻的所有顶点。
如果从当前扩展结点i到顶点j有边可达,且从源出发,途经顶点i再到顶点j的所相应的路径的长度小于当前最优路径长度,则将该顶点作为活结点插入到活结点优先队列中。
这个结点的扩展过程一直继续到活结点优先队列为空时为止。
在算法扩展结点的过程中,一旦发现一个结点的下界不小于当前找到的最短路长,则算法剪去以该结点为根的子树。
在算法中,利用结点间的控制关系进行剪枝。
从源顶点s出发,2条不同路径到达图G
的同一顶点。
由于两条路径的路长不同,因此可以将路长长的路径所对应的树中的结点为根的子树剪去。
#include"
stdafx.h"
MinHeap2.h"
6d2.txt"
classGraph
friendintmain();
public:
voidShortesPaths(int);
private:
int
n,
//图G的顶点数
*prev;
//前驱顶点数组
Type
**c,
//图G的领接矩阵
*dist;
//最短距离数组
};
classMinHeapNode
friendGraph<
Type>
operatorint()const{returnlength;
inti;
//顶点编号
Typelength;
//当前路长
voidGraph<
:
ShortesPaths(intv)//单源最短路径问题的优先队列式分支限界法
MinHeap<
MinHeapNode<
H(1000);
E;
//定义源为初始扩展节点
E.i=v;
E.length=0;
dist[v]=0;
while(true)//搜索问题的解空间
for(intj=1;
j<
=n;
if((c[E.i][j]!
=0)&
(E.length+c[E.i][j]<
dist[j])){
//顶点i到顶点j可达,且满足控制约束
dist[j]=E.length+c[E.i][j];
prev[j]=E.i;
//加入活结点优先队列
N;
N.i=j;
N.length=dist[j];
H.Insert(N);
}'
try
H.DeleteMin(E);
//取下一扩展结点
catch(int)
break;
if(H.currentsize==0)//优先队列空
intmain()
intn=11;
intprev[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};
co