博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【算法概论】动态规划:最短路径问题
阅读量:4176 次
发布时间:2019-05-26

本文共 2456 字,大约阅读时间需要 8 分钟。


因为刚开始想着,既然在图中表示,就要用到图的存储结构等等吧,所以 ?

首先,要复习一下图的相关知识(学完数据结构后过了不长的时间,已经还给老师了?)

1、图的存储结构:

       邻接矩阵表示法 和 邻接表表示法(详见 )。

2、图的基本算法:

       计算图的顶点数量,计算图的边数量,返回第i个顶点的值,插入一个顶点,删除一个顶点,插入一条边,删除一条边,深度优先遍历图,广度优先遍历图。

       拓扑排序


接着,来看下面这道多段图中的最短路径问题(The shortest path in multistage graphs)

问题描述:

       建立一个从源点S到终点T的多段图,设计一个动态规划算法求出从S到T的最短路径值,并输出相应的最短路径。 

解决思路(老师讲课):

       首先,暴力法是遍历从 S 到 T 的所有路径,依次比较。

       但我们可以使用更优的方法 —— 动态规划。

       很容易看出,这是一个多阶段决策的问题,S —— A、B、C —— D、E、F —— T 分别是四个阶段,如下图所示:

       按照 自底向上(bottom-up) 的方法,d(S, T) = min{ 1 + d(A, T), 2 + d(B, T), 5 + d(C, T) };这满足 动态规划 的 最优子结构 的性质,即,问题的最优解包含其子问题的最优解。

算法实现(老师讲课):

/*伪代码*/d[1] = 0for j = 2 to n:    for all 
∈E : d[j] = min{ d[i] + w [i,j] }return d[n]

有向无环图中的最短路径问题(The shortest path in dags):

问题描述:

       建立一个从源点S到终点E的有向无环图,设计一个动态规划算法求出从S到E的最短路径值,并输出相应的最短路径。

解决思路(老师讲课):

       有向无环图不像多段图,有明确的分阶段,它能转换成多段图进行求解吗?

       也可以,因为,有向无环图 可以通过 拓扑排序 将其转换为 线性结构。

       Notice that, the special distinguishing feature of a dag is that its nodes can be linearized; that is, they can be arranged on a line so that all edges go from left to right. 如下图所示:

        (回到了这篇文章开头的地方)。

算法实现:

       从图中可以看出:

/*伪代码*/initialize all dist(.) values to    dist(s) = 0for each v V\{s}, in linearized order;    dist(v)=min {dist(u) + (u,v)}

       所以我本来想着要用着邻接表啊一些数据结构的知识,便复习了一番,最终代码太繁琐,在deadline之前调不完了……

……so,先暂空着……

 

However,

       在网上查找相关代码的时候,发现了如下的代码,自己又改了一部分:

#include 
#include
using namespace std;int main(){ cout << "请输入图的顶点数目:" << endl; int vexnum; cin >> vexnum; vector
cost(vexnum, 0); //cost[i]表示从顶点i到终点n-1的最短路径长度 vector
path(vexnum, 0); //path[i]表示从顶点i到终点n-1的路径上顶点i的下一个顶点 cout << "请输入图的边数:" << endl; int edgenum; cin >> edgenum; vector
> edge(vexnum, vector
(vexnum, 0)); //edge[i][j]存储多段图中的边 cout << "请依次输入图中各边的起点终点和路径长度:" << endl; int start; int end; int length; for (int i = 0; i < edgenum; ++i) { cin >> start >> end >> length; edge[start][end] = length; } for (int i = vexnum-2; i >= 0; --i) { cost[i] = INT_MAX; for (int j = i; j < vexnum; ++j) { if (edge[i][j] != 0) { //等于零表示之间没有路 if (edge[i][j] + cost[j] < cost[i]) { //此时找到一条更短的路 path[i] = j; //更新path[i] cost[i] = edge[i][j] + cost[j]; //更新从该节点出发的最短路径 } } } } cout << "最短路径长度是:" << cost[0] << endl; cout << "最短路径为:" << endl; int i = 0; cout << "0 ---> "; while (1) { cout << path[i]; i = path[i]; if (i == vexnum-1) { break; } cout << " ---> "; } cout << endl; return 0;}

       其实,这种代码,适用于上述两种最短路径的情况,只要确定了各顶点的序号,输入就OK啦!

转载地址:http://pttai.baihongyu.com/

你可能感兴趣的文章
Yocto tips (4): Yocto 如何确定(找到)一个包的名字
查看>>
start kernel 之后没有任何输出与uboot无法将bootargs传入内核的调查方法与解决之道
查看>>
Yocto tips (5): Yocto如何更改source code的下载与git clone地址
查看>>
Yocto tips (7): Yocto Bitbake的clean与cleanall以及cleansstate的区别
查看>>
Yocto tips (19): Yocto SDK Toolchian的使用
查看>>
Yocto i.MX6 (TQIMX6) (04) : 使用mjpg-streamer做一个WebCam Server
查看>>
Nexus 7 Cyanogenmod OS Compile and errors
查看>>
Yocto tips (20): Yocto中qemu模拟器的使用,以zynq Cortex-A9为例
查看>>
打造嵌入式ARM Linux防火墙:1. iptables基础
查看>>
4G模块SIMCOM7100 LTE在ARM Linux下使用PPPD上网
查看>>
为小米4与小米3 Mi3 Mi4编译Cyanogenmod 12.1与13.0 (CM12与CM13) 的步骤以及错误解决
查看>>
原生Android系统的第一次开机google验证的解决
查看>>
S5P4418与S5P6618的Android boot.img的解压与压缩, Sparse ext4文件系统
查看>>
【EVB-335X-II试用体验】 u-boot与kernel的编译以及本地repo的建立
查看>>
【EVB-335X-II试用体验】 上手试用与资源使用
查看>>
【EVB-335X-II试用体验】 Yocto环境的建立及Rootfs的构建与使用
查看>>
<<C++程序设计原理与实践>>粗读--chapter0 chapter1 chapter2
查看>>
<<C++程序设计原理与实践>>粗读--chapter3 chapter4 Chapter5
查看>>
<<C++程序设计原理与实践>>粗读 -- chapter8 Chapter9
查看>>
Linux Qt程序打包成一个可执行文件
查看>>