Floyd 算法精讲
题目链接/文章讲解:https://www.programmercarl.com/kamacoder/0097.%E5%B0%8F%E6%98%8E%E9%80%9B%E5%85%AC%E5%9B%AD.html
解题思路:
- 确定dp数组(dp table)以及下标的含义
这里我们用 grid数组来存图,那就把dp数组命名为 grid。
grid[i][j][k] = m,表示 节点i 到 节点j 以[1...k] 集合中的一个节点为中间节点的最短距离为m。
节点i 到 节点j 的最短路径中 一定是经过很多节点,那么这个集合用[1...k] 来表示。
- 确定递推公式
我们分两种情况:
- 节点i 到 节点j 的最短路径经过节点k
- 节点i 到 节点j 的最短路径不经过节点k
对于第一种情况,grid[i][j][k] = grid[i][k][k - 1] + grid[k][j][k - 1]
节点i 到 节点k 的最短距离 是不经过节点k,中间节点集合为[1...k-1],所以 表示为grid[i][k][k - 1]
节点k 到 节点j 的最短距离 也是不经过节点k,中间节点集合为[1...k-1],所以表示为 grid[k][j][k - 1]
第二种情况,grid[i][j][k] = grid[i][j][k - 1]
如果节点i 到 节点j的最短距离 不经过节点k,那么 中间节点集合[1...k-1],表示为 grid[i][j][k - 1]
因为我们是求最短路,对于这两种情况自然是取最小值。
即: grid[i][j][k] = min(grid[i][k][k - 1] + grid[k][j][k - 1], grid[i][j][k - 1])
- dp数组如何初始化
grid[i][j][k] = m,表示 节点i 到 节点j 以[1...k] 集合为中间节点的最短距离为m。
刚开始初始化k 是不确定的。
所以 只能 把k 赋值为 0,本题 节点0 是无意义的,节点是从1 到 n。
这样我们在下一轮计算的时候,就可以根据 grid[i][j][0] 来计算 grid[i][j][1],此时的 grid[i][j][1] 就是 节点i 经过节点1 到达 节点j 的最小距离了。
所以初始化代码:
vector<vector<vector<int>>> grid(n + 1, vector<vector<int>>(n + 1, vector<int>(n + 1, 10005))); // C++定义了一个三位数组,10005是因为边的最大距离是10^4
for(int i = 0; i < m; i++){
cin >> p1 >> p2 >> val;
grid[p1][p2][0] = val;
grid[p2][p1][0] = val; // 注意这里是双向图
}
- 确定遍历顺序
从递推公式:grid[i][j][k] = min(grid[i][k][k - 1] + grid[k][j][k - 1], grid[i][j][k - 1])
可以看出,我们需要三个for循环,分别遍历i,j 和k
而 k 依赖于 k - 1, i 和j 的到 并不依赖与 i - 1 或者 j - 1 等等。
所以遍历k 的for循环一定是在最外面,这样才能一层一层去遍历。
- 举例推导dp数组
A * 算法精讲 (A star算法)
解题思路:
Astar 是一种 广搜的改良版。 有的是 Astar是 dijkstra 的改良版。
而 Astar 关键在于 启发式函数, 也就是 影响 广搜或者 dijkstra 从 容器(队列)里取元素的优先顺序。
BFS 是没有目的性的 一圈一圈去搜索, 而 A * 是有方向性的去搜索。
对队列里节点进行排序,就需要给每一个节点权值,如何计算权值呢?
每个节点的权值为F,给出公式为:F = G + H
G:起点达到目前遍历节点的距离
H:目前遍历的节点到达终点的距离
起点达到目前遍历节点的距离 + 目前遍历的节点到达终点的距离 就是起点到达终点的距离。
计算出来 F 之后,按照 F 的 大小,来选去出队列的节点。
可以使用 优先级队列 帮我们排好序,每次出队列,就是F最小的节点。
最短路算法总结篇
了解最短路算法和使用场景。
至此已经讲解了四大最短路算法,分别是Dijkstra、Bellman_ford、SPFA 和 Floyd。
如果遇到单源且边为正数,直接Dijkstra。
至于 使用朴素版还是 堆优化版 还是取决于图的稠密度。
如果遇到单源边可为负数,直接 Bellman-Ford,同样 SPFA 还是 Bellman-Ford 取决于图的稠密度。
如果有负权回路,优先 Bellman-Ford, 如果是有限节点最短路 也优先 Bellman-Ford,理由是写代码比较方便。
如果是遇到多源点求最短路,直接 Floyd。
图论总结
题目链接/文章讲解:https://www.programmercarl.com/kamacoder/%E5%9B%BE%E8%AE%BA%E6%80%BB%E7%BB%93%E7%AF%87.html
了解图的存储方式,邻接表和邻接矩阵
了解深搜与广搜在图这个数据结构上的搜索过程
了解并查集的应用
了解最小生成树
了解拓扑排序
了解最短路算法
总结
第62天,完结