BFS寻最短路径
图大致分为两类:有权图和无权图。
普通的bfs遍历能够直接找到无权图的最短路径。 对于有权图,bfs并不能直接找到最短路径,这时需要使用dijkstra算法。
dijkstra算法的基本思路是:维护一个最小堆,每次从中取出一个距离最小的点,然后更新它的邻居节点的距离,直到所有点的最短路径都被找到。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
int bfs(vector<vector<int>> &grid)
{
int n = grid.size();
vector<vector<bool>> visited(n, vector<bool>(n, false));
queue<vector<int>> q;
q.push({0, 0});
visited[0][0] = true;
int steps = 0;
while (!q.empty())
{
int s = q.size();
for (int i = 0; i < s; i++)
{
auto &cur = q.front();
q.pop();
int cur_x = cur[0], cur_y = cur[1];
if (cur_x == n - 1 && cur_y == n - 1)
{
return steps;
}
for (int j = 0; j < 4; j++)
{
int nx = cur_x + dirs[j];
int ny = cur_y + dirs[j + 1];
if (0 <= nx && nx < n && 0 <= ny && ny < n && !visited[nx][ny])
{
q.push({nx, ny});
visited[nx][ny] = true;
}
}
}
steps++;
}
return -1;
}
或者将路径长度信息包含包含在队列节点中,此时不需要按层遍历。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int bfs(vector<vector<int>> &grid)
{
int n = grid.size();
vector<vector<bool>> visited(n, vector<bool>(n, false));
queue<vector<int>> q;
q.push({0, 0, 0});
visited[0][0] = true;
while (!q.empty())
{
auto &cur = q.front();
q.pop();
int cur_x = cur[0], cur_y = cur[1], cur_step = cur[2];
if (cur_x == n - 1 && cur_y == n - 1)
{
return cur_step;
}
for (int j = 0; j < 4; j++)
{
int nx = cur_x + dirs[j];
int ny = cur_y + dirs[j + 1];
if (0 <= nx && nx < n && 0 <= ny && ny < n && !visited[nx][ny])
{
q.push({nx, ny, cur_step + 1});
visited[nx][ny] = true;
}
}
}
return -1;
}
在写下dijkstra算法, dijkstra 不需要进行visited标记,因为无法更新当前最短路径的节点不会被重新放入队列。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int dijkstra(vector<vector<int>> &grid)
{
int n = grid.size();
vector<vector<int>> dist(n, vector<int>(n, INT_MAX));
dist[0][0] = 0;
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
pq.push({0, 0, 0});
while (!pq.empty())
{
auto &cur = pq.top();
pq.pop();
int cur_dist = cur[0], cur_x = cur[1], cur_y = cur[2];
if (cur_x == n - 1 && cur_y == n - 1)
{
return cur_dist;
}
for (int j = 0; j < 4; j++)
{
int nx = cur_x + dirs[j];
int ny = cur_y + dirs[j + 1];
if (0 <= nx && nx < n && 0 <= ny && ny < n)
{
int new_dist = cur_dist + grid[nx][ny];
if (new_dist < dist[nx][ny])
{
dist[nx][ny] = new_dist;
pq.push({new_dist, nx, ny});
}
}
}
}
return -1;
}
This post is licensed under CC BY 4.0 by the author.