目录
算法描述
1.伪代码
MultiStageGraph(G, k, n, p[]) {
//输入 n 个结点的 k 段图,假设顶点按段的顺序编号
//E(G)是边集,p[1,2,…,k]是最小成本路径
new cost[n];
new d[n];
cost[0] = 0;
for i = 1 upto n-1 do {
cost[i] = ∞;
while (任意<i, r>∈E(G)) {
if (c(i, r) + cost[r] < cost[i]) {
cost[i] = c(i, r) + cost[r];
d[i] = r;
}
}
}
p[0] = 0;
p[k-1] = n;
for i = 0 to k - 1 do {
p[i] = d[p[i]];
}
}
2.代码思路
通过动态规划的方式,逐步计算每个节点的最小成本,并最终得到最小成本路径。首先对节点的成本进行初始化,然后通过遍历每个节点,计算出每个节点的最小成本。最后输出最小代价和计算得到的最小成本路径。
源代码
def MultiStageGraph(G, k, n, p):
"""
计算 n 个结点的 k 段图中的最小成本路径
Args:
G (list): 边集,每个元素是一个三元组 (起点, 终点, 成本)
k (int): 图的段数
n (int): 结点个数
p (list): 用于存储最小成本路径的列表,长度为 k
Returns:
无返回值,最小成本路径存储在参数 p 中
"""
cost = [0] * n # 存储每个节点的最小成本
d = [-1] * n # 存储对应最小成本路径的前一个节点
cost[0] = 0 # 起始节点的成本为 0
# 计算每个节点的最小成本
for i in range(1, n):
cost[i] = float('inf') # 初始化成本为无穷大
for edge in G:
if edge[1] == i: # 只考虑终点在当前结点的边
r = edge[0] # 起点
if edge[2] + cost[r] < cost[i]: # 如果经过当前边到达终点的成本更小
cost[i] = edge[2] + cost[r] # 更新最小成本
d[i] = r # 记录对应最小成本路径的前一个节点
print("最小代价为:", cost[n-1])
# 计算最小成本路径
p[0] = 0
p[k-1] = n-1
for i in range(k - 2, 0, -1):
p[i] = d[p[i+1]]
# 用户输入
n = int(input("请输入节点数n:"))
k = int(input("请输入段数k:"))
edge_num=int(input("请输入边数:"))
G = []
print("输入边(起点 终点 成本)")
for _ in range(edge_num):
edge = tuple(map(int, input().split()))
G.append(edge)
p = [0] * k
# 调用算法并输出结果
MultiStageGraph(G, k, n, p)
print("路径为:",p)
复杂度分析
时间复杂度取决于节点数 n、段数 k 和边数 m。
初始化 cost 和 d 列表的时间复杂度为 O(n)。
计算每个节点的最小成本的时间复杂度为 O(m*n),因为对于每个节点,都需要考虑每条边。
计算最小成本路径的时间复杂度为 O(k),因为只需遍历段数次。
因此,总体时间复杂度为 O(m*n + k)。
空间复杂度方面,主要是存储了两个长度为 n 的列表 cost 和 d,以及一个长度为 k 的列表 p,因此空间复杂度为 O(n + k)。
程序的运行结果及截图
测试数据:
0 1 9
0 2 7
0 3 3
0 4 2
1 5 4
1 6 2
1 7 1
2 5 2
2 6 7
3 7 11
4 6 11
4 7 8
5 8 6
5 9 5
6 8 4
6 9 3
7 9 5
7 10 6
8 11 4
9 11 2
10 11 99
总结与改进
实现了多段图中的最小成本路径计算算法。通过动态规划的方式,逐步计算每个节点的最小成本,并最终得到最小成本路径。首先对节点的成本进行初始化,然后通过遍历每个节点,计算出每个节点的最小成本。最后输出最小代价和计算得到的最小成本路径。
但是,在该算法中,如果多段图有两条或两条以上的最短路径(代价相同,路径不同),那么该算法只能给出一条,修改时,需要把路径p设置成一个多维列表,储存多个最短路径,还要把d设置成多维变量,以储存到达i结点的代价相同的n个前置结点,仍然复杂。
因此,设计如下通过深度优先搜索,可以找到所有的最短路径,以下是代码和结果。
def MultiStageGraph(G, k, n, p):
"""
计算 n 个结点的 k 段图中的最小成本路径
Args:
G (list): 边集,每个元素是一个三元组 (起点, 终点, 成本)
k (int): 图的段数
n (int): 结点个数
p (list): 用于存储最小成本路径的列表
Returns:
无返回值,最小成本路径存储在参数 p 中
"""
cost = [0] * n # 存储每个节点的最小成本
cost[0] = 0 # 起始节点的成本为 0
# 计算每个节点的最小成本和路径数量
for i in range(1, n):
cost[i] = float('inf') # 初始化成本为无穷大
for edge in G:
if edge[1] == i: # 只考虑终点在当前结点的边
r = edge[0] # 起点
if edge[2] + cost[r] < cost[i]: # 如果经过当前边到达终点的成本更小
cost[i] = edge[2] + cost[r] # 更新最小成本
print("最小代价为:", cost[n-1])
# 使用深度优先搜索找到所有的最短路径
def dfs(u, path):
if u == 0:
p.append(path[::-1])
return
for edge in G:
if edge[1] == u and cost[u] == cost[edge[0]] + edge[2]:
dfs(edge[0], path + [edge[0]])
dfs(n-1, [n-1])
print("最小成本路径为:", p)
# 用户输入
n = int(input("请输入节点数n:"))
k = int(input("请输入段数k:"))
edge_num = int(input("请输入边数:"))
G = []
print("输入边(起点 终点 成本)")
for _ in range(edge_num):
edge = tuple(map(int, input().split()))
G.append(edge)
p = []
# 调用算法并输出结果
MultiStageGraph(G, k, n, p)