【算法】用动态规划求解最短路径问题

1. 问题描述

给定先把图 G(V,E),用动态规划的算法求一条从起点到终点的路径,使这条路径上经过的所 有边的权重之和最小。
在这里插入图片描述

2. 算法描述

2.1 动态规划描述

动态规划是一种用来解决一类最优化问题的算法思想,将一个复杂的问题分解成若干个子问 题,通过综合子问题的最优解来得到原问题的最优解。动态规划会将每个求解过的子问题的 解记录下来,这样下一次碰到同样的子问题时,就可以直接使用之前记录的结果。
在动态规划中,我们通常使用两种办法来求解:递推的自底向上办法(Bottom-up)递归的 自顶向下办法(Top-down),在本题我们采用递推的自底向上办法。
在最短路径问题中,我们首先要找到路径图中的拓扑排序顺序,作为递推的顺序。因为只有 知道当前节点所有入度节点的路径最大值,我们才能知道该节点的状态最优解。

2.2 拓扑排序

下面是拓扑排序的算法:

  1. 定义一个队列 Q,并把所有入度为 0 的节点加入序列。
  2. 取队列首节点,输出。然后删去所有从它出发的边。并另这些边到达顶点的入度减 1,如
    果某个顶点的入度减为 0,则将其加入队列。
  3. 反复进行步骤 2,直到队列为空。

当前节点 0 的入度为 0,将该节点加入序列中。用 S 记录下拓扑排序的顺序。S = [0]
在这里插入图片描述
删除从节点 0 出发的所有边
在这里插入图片描述
在这里插入图片描述
当前入度为 0 的节点为节点 1 和节点 6,将这两个节点加入序列并依次执行步骤 2 操作。 S=[0,6,1]
在这里插入图片描述
在这里插入图片描述
在当前的路径图中,节点 3 的入度为 0,加入队列,并执行步骤 2。S=[0,1,6,3]
在这里插入图片描述
在这里插入图片描述
将顶点 2 加入序列,并执行步骤 2。S=[0,1,6,3,2]
在这里插入图片描述
在这里插入图片描述
当前顶点 5 是入度为 0 的顶点,将其加入队列并执行步骤 2。S=[0,1,6,3,2,5]
在这里插入图片描述
在这里插入图片描述
顶点 4 是入度为 0 的节点,将其加入队列,并执行步骤 2。S=[0,1,6,3,2,5]
在这里插入图片描述
在这里插入图片描述
到达节点 7,将终点加入 S,S=[0,1,6,3,2,5,7],我们得到了拓扑排序的顺序

2.3 递推(Bottom-up Approach)

在得到拓扑排序 S=[0,1,6,3,2,5,7]后,我们使用动态规划的递推方法来得到该路径图从起点 到终点的最短路径。
在当前节点中考虑该节点所有入度的情况,比较上一跳最短路径加上上一跳到该节点的路径 长度的和与其他节点指向该节点的最短路径的长的大小。我们可以得到下面的表格。
在这里插入图片描述

3. 实验代码

// An highlighted block
import copy 
#拓扑排序
def topological_order(paths,indegree): 
	tempindegree = copy.deepcopy(indegree) 
	order = [] 
	for i in range(len(tempindegree)): 
		if tempindegree[i] == 0: 
			order.append(i) 
	num = 1 
	finalorder = [] 
	while len(order) != 0: 
		u = order.pop() 
		finalorder.append(u) 
		if num == len(tempindegree): 
			print("拓扑排序:",finalorder) 
			return finalorder 
	
		for j in range(len(paths)): 
			if paths[j][0] == u: 
				v = paths[j][1] 
				tempindegree[v] = tempindegree[v] - 1 
				if tempindegree[v] == 0: 
					order.append(v) 
					num = num + 1 
					#print(order)

if __name__ == "__main__": 
	paths = [ 
		#用邻接表存储下这张表 
		[0,1,5], 
		[0,6,3], 
		[1,2,2], 
		[1,3,1], 
		[2,4,7], 
		[2,5,3], 
		[3,2,1], 
		[3,4,2], 
		[3,5,1], 
		[4,7,1], 
		[5,4,2], 
		[5,7,5], 
		[6,2,2] ]
	
	#存储每个节点的入度 
	indegree = [0,1,2,1,3,2,1,2]
	finalorder = topological_order(paths,indegree) 
	#每个节点当前的最短路径长度和上一跳的节点 
	length = [0,0,0,0,0,0,0,0] 
	lastnode = [-1,-1,-1,-1,-1,-1,-1,-1]
	for i in finalorder: 
		for j in range(len(paths)): 
			if i == paths[j][1]: 
				if length[i] != 0 and length[i] < (length[paths[j][0]] + paths[j][2]): 
					continue 
				else:
					#print("节点:",i,"path:",length[paths[j][0]],",", paths[j][2]) 
					length[i] = length[paths[j][0]] + paths[j][2] 
					lastnode[i] = paths[j][0] 
	print("节点当前走过的最短路径",length) 
	print("上一跳节点",lastnode) 
	shortestpath = [] 
	index = len(lastnode) - 1 
	while index != 0: 
		shortestpath.append(index) 
		index = lastnode[index] 
	shortestpath.append(0) 
	shortestpath.reverse() 
	print("最短路径的长度:",length[-1]) 
	print("最短路径:",shortestpath)

4. 实验结果

成功运行代码后,我们得到了下面的实验结果。
在这里插入图片描述
这与我们的推论相符,实验成功。 在该问题中的最优子结构为每个节点相应的最短路径,使用拓扑排序我们肯定可以得到当前 节点所有入度情况并进行分析比较。通过记录下当前问题的最优子结构,我们可以避免重叠 问题的重复求解,这种动态规划的思想很好地提高了算法的效率。

参考和致谢

[1]胡凡,曾磊.算法笔记[M].机械工业出版社:北京,2016.7:390-392.
[2]【MIT 课程】动态规划 I-最短路径算法 https://www.bilibili.com/video/BV1Y441157H7
[3]漫画:什么是动态规划?(整合版) https://www.sohu.com/a/149075950_684445

  • 20
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
蚁群算法是一种模拟蚂蚁觅食行为的算法,用于解决路径规划问题。它适用于求解最短路径问题,包括求解最短路径和最优路径等。 下面以一个简单的案例来说明蚁群算法在路径规划中的应用。 假设有一个城市地图,其中有多个城市之间的连接道路,我们需要找到从起点城市到终点城市的最短路径。 首先,我们需要将每个城市看作一个节点,并根据道路的距离来确定节点之间的边。然后,将一定数量的蚂蚁放置在起点城市,并让它们开始在城市间移动。 蚂蚁会根据一定的算法来选择下一个要访问的城市。通常情况下,蚂蚁更倾向于选择距离当前城市更近的城市,并且会受到已经被其他蚂蚁选择的路径的影响(信息素)。 当蚂蚁到达终点城市后,我们会评估它们所选择的路径长度,并根据路径长度来更新信息素。较短路径上的蚂蚁会释放更多的信息素,而较长路径上的蚂蚁会释放较少的信息素。这样,信息素会在城市间逐渐累积,进而影响其他蚂蚁的选择。 通过多轮迭代,蚂蚁们会逐渐找到一条最短路径,并且这条路径上的信息素含量会越来越高。最终,我们可以选择信息素含量最高的路径作为最优解,即最短路径。 需要注意的是,蚁群算法是一种启发式算法,其结果并不一定是全局最优解,但通常情况下能够找到较好的解决方案。 以上就是蚁群算法在路径规划中求解最短路径的一个简单案例。在实际应用中,蚁群算法还可以应用于其他领域的优化问题,如资源调度、旅行商问题等。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值