Floyd算法解决的是全源最短路径问题,即计算图中任意两个节点之间的最短路径;基于动态规划。通过考虑所有节点作为中间节点的可能性,来系统地更新任意两点间的最短距离。
- 时间复杂度,空间复杂度,适用于任何图,不论有向无向、不管边权值正负,但不能有负环(即保证最短路存在)
- 考察从i到j的距离distance[i][j]能不能通过一个中间点bridge来缩短,即distance[i][j]是否小于distance[i][bridge]+ distance[bridge][j]
#include <climits>
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
int defaultValue = 10001;
vector<vector<int>> grid(n + 1, vector<int>(n + 1, defaultValue));
int from, to, weight;
for (int i = 0; i < m; ++i) {
cin >> from >> to >> weight;
grid[from][to] = weight;
grid[to][from] = weight;
}
for (int bridge = 1; bridge <= n; ++bridge) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (grid[i][bridge] != defaultValue &&
grid[bridge][j] != defaultValue &&
grid[i][j] > grid[i][bridge] + grid[bridge][j]) {
grid[i][j] = grid[i][bridge] + grid[bridge][j];
}
}
}
}
int Q = 0;
cin >> Q;
int start, end;
for (int i = 0; i < Q; ++i) {
cin >> start >> end;
cout << (grid[start][end] == defaultValue ? -1 : grid[start][end]) << endl;
}
return 0;
}
指定源点、指定目标点,求源点到目标点的最短距离。
增加了当前点到终点的预估距离
加入小根堆时,用的是源点到当前点的距离+当前点到终点的预估距离
其余与Dijkstra算法相同
A* 算法是一种启发式搜索算法,主要用于在静态图中寻找单一目标点的最短路径。它是对Dijkstra算法的优化,通过引入一个启发式函数来指导搜索方向。在Dijkstra的基础上,不仅考虑从源点到当前节点的实际代价 g(n),还估计从当前节点到目标节点的预计代价 h(n)。它总是优先选择 f(n) = g(n) + h(n) 值最小的节点进行扩展。
预估函数一般选择:曼哈顿距离,欧式距离,对角线距离
#include <climits>
#include <cstring>
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
const int m = 1000;
int moves[1001][1001];
class Knight {
public:
int x;
int y;
int g, h, f;
// 从小到大
bool operator<(const Knight &k) const { return k.f < f; }
};
priority_queue<Knight, vector<Knight>> pq;
int h(int a1, int a2, int b1, int b2) {
return (b1 - a1) * (b1 - a1) + (b2 - a2) * (b2 - a2);
}
int dirs[8][2] = {-2, -1, -2, 1, -1, 2, 1, 2, 2, 1, 2, -1, 1, -2, -1, -2};
int Astar(int a1, int a2, int b1, int b2) {
Knight cur, next;
while (!pq.empty()) {
cur = pq.top();
pq.pop();
if (cur.x == b1 && cur.y == b2)
break;
for (auto dir : dirs) {
next.x = cur.x + dir[0];
next.y = cur.y + dir[1];
if (next.x < 1 || next.x > m || next.y < 1 || next.y > m) {
continue;
}
if (!moves[next.x][next.y]) {
moves[next.x][next.y] = moves[cur.x][cur.y] + 1;
next.g = cur.g + 5;
next.h = h(next.x, next.y, b1, b2);
next.f = next.g + next.h;
pq.push(next);
}
}
}
return moves[b1][b2];
}
int main() {
int n;
cin >> n;
int a1, a2, b1, b2;
for (int i = 0; i < n; ++i) {
cin >> a1 >> a2 >> b1 >> b2;
memset(moves, 0, sizeof(moves));
Knight knight;
knight.x = a1;
knight.y = a2;
knight.g = 0;
knight.h = h(a1, a2, b1, b2);
knight.f = knight.g + knight.h;
pq.push(knight);
cout << Astar(a1, a2, b1, b2) << endl;
while (!pq.empty()) {
pq.pop();
}
}
return 0;
}