浅谈路径规划算法之Bellman-Ford算法
来源:互联网 发布:袅袅虚拟歌手 mac 编辑:程序博客网 时间:2024/05/29 15:43
最近在研究AGV系统的调度算法,为了实现多AGV小车的运行,给每一个AGV小车规划一条最优路径,对比了Bellman-Ford算法、SPFA算法、Dijkstra算法、Floyd算法和A*算法的优缺点,最终确定了使用A*算法作为路径规划算法。
下面总结下几种算法:
1、Bellman-Ford算法
(1)贝尔曼-福特算法是计算从源点到任意一点的最短路径的长度,初始化数组dist[0]为0,dist[i]为无穷大。
(2)以下操作循环执行至多n-1次,n为顶点数:
对于每一条边 edge(Start,End),如果dist[Start] +Weight(Start, End)<dist[End],则令dist[End] =dist[Start]+Weight(Start, End)。若上述操作没有对dist进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;
为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边dge(Start,End),如果存在dist[Start] + Weight(Start, End) < dist[End]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组dist[n]中记录的就是源点s到各顶点的最短路径长度。
注释:Start是一条有向边的起点,End是一条有向边的终点;edge(Start,End)为节点Start和节点End之间边;Weight(Start, End)为节点Start和节点End之间的边的权值;dist[i]是指源节点到i节点的距离;
Bellman-Ford算法可以大致分为三个部分
第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。
第二,进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。
第三,遍历途中所有的边(edge(u,v)),判断是否存在这样情况:d(v)> d (u) + w(u,v)则返回false,表示途中存在从源点可达的权为负的回路。
!!!之所以需要第三部分的原因,是因为,如果存在从源点可达的权为负的回路。则 应为无法收敛而导致不能求出最短路径。
经过第一次遍历后,点B的值变为5,点C的值变为8,这时,注意权重为-10的边,这条边的存在,导致点A的值变为-2。(8+ -10=-2)
第二次遍历后,点B的值变为3,点C变为6,点A变为-4。正是因为有一条负边在回路中,导致每次遍历后,各个点的值不断变小。所以这是无限循环的。
下面是Bellman-Ford算法的实现代码:
#include <iostream>#include <stdio.h>using namespace std;const int maxnum=100; //最大边数const int maxint=9999; //源点和某点不可达时的距离//有向边的结构体typedef struct Edge{ int Start; //有向边边的起始点 int End; //有向边的终点 int Weight;//边的权重}Edge;Edge edge[maxnum];//有向边的数组int dist[maxnum]; //距离数组//节点的数目、边的数目、源节点的下标int nodenum,edgenum,source;//初始化函数void Init(){ cin>>nodenum>>edgenum>>source; for(int i=1;i<=nodenum;i++) dist[i]=maxint; dist[source]=0; for(int i=1;i<=edgenum;i++) { cin >> edge[i].Start >> edge[i].End >> edge[i].Weight; if(source==edge[i].Start) { dist[edge[i].End]=edge[i].Weight; } }}//松弛函数void Relax(int Start,int End,int Weight){ if(dist[End]>dist[Start]+Weight) dist[End]=dist[Start]+Weight;}//贝尔曼福特函数bool Bellman_Ford(){ for(int i=1;i<=nodenum-1;i++) { for(int j=1;j<=edgenum;j++) { Relax(edge[j].Start,edge[j].End,edge[j].Weight); } } bool flag=1; for(int i=1;i<=edgenum;i++) { //判断是否存在负回路 if(dist[edge[i].End]>dist[edge[i].Start]+edge[i].Weight) { flag=0; break; } } return flag;}int main(){ freopen("out.txt","r",stdin);//打开txt Init(); if(Bellman_Ford()) { for(int i=1;i<nodenum;i++) cout<<dist[i]<<endl;//打印源节点到每个节点的距离 } return 0;}
贝尔曼算法的时间复杂度是O(V*E),是非常大的,所以它的效率非常低。
- 浅谈路径规划算法之Bellman-Ford算法
- 单源最短路径算法之Bellman-Ford算法
- 求最短路径之Bellman-Ford算法
- 【算法】最短路径之Bellman-Ford
- 单源最短路径之Bellman-Ford 算法
- 单源最短路径之Bellman-Ford算法
- Bellman-Ford算法之单源最短路径问题
- Bellman-Ford算法---求包含负权边单源最短路径(动态规划)
- 单源最短路径Bellman-Ford算法
- 单源最短路径 : Bellman-Ford 算法
- 单源最短路径-Bellman-Ford算法
- 单源最短路径--Bellman-Ford算法
- 单源最短路径-Bellman-Ford算法
- 单源最短路径-Bellman-ford算法
- Bellman-Ford 单源最短路径算法
- 【算法导论】单源最短路径之Bellman-Ford算法
- 算法笔记---最短路径之bellman-ford算法
- 贪心算法之Bellman-Ford
- Python条件、循环和其他语句
- 嵌入式linux驱动-触摸屏笔记
- Linux面试题集锦四
- [BZOJ1937][Shoi2004]Mst 最小生成树(KM)
- eclipse + 开发 PHP 环境搭建
- 浅谈路径规划算法之Bellman-Ford算法
- 几张图轻松理解String.intern()
- Java连接MySql中Url指定字符集
- RactiveJS-12 Lifecycle eventes
- 4.5学习内容
- matlab中调用c++函数
- 骰子1-6次数, labview
- jvm的内存分配机制
- 闲谈