#搜索 #基础算法
宽度优先搜索 BFS
(层次扩展+队列+边权为1的最短路)
核心思想
- 从起点出发,一层一层向外扩散;先到的层就是最短路径
模板
cpp
void bfs()
{
memset(dist, -1, sizeof dist);
queue<PII> q;
q.push({x, y}); // 插入队列
dist[x][y] = 0; // 起始节点初始化为 0
while (q.size())
{
auto t = q.front(); q.pop(); // 拿出后删掉队头
for (int k = 0; k < 8; k++) // 八个方向遍历
{
int i = t.first, j = t.second;
int x = i + dx[k], y = j + dy[k];
if (x < 1 || x > n || y < 1 || y > m) continue; // 越界剪枝
if (dist[x][y] != -1) continue; // 访问过剪枝
dist[x][y] = dist[i][j] + 1; // 更新结果
q.push({x, y}); // 插入队尾
}
}
}
多源BFS
初始化:
cpp
for 所有起点 p
dist[p] = 0, q.push(p);
//其余代码与单源完全一致;第一次访问即最短距离。
01-BFS(边权只有0或1)
- 0 权边 → 插队头 push_front
- 1 权边 → 插队尾 push_back
- 用双端队列 deque ,仍保证"层"有序
- 复杂度 O(V+E)。
cpp
int dfs01(int x1, int y1, int x2, int y2) {
memset(dist, -1, sizeof dist); // 距离表初始化为"未访问"
deque<pair<int, int>> q; // 双端队列:0 权头插,1 权尾插
q.push_back({x1, y1}); // 起点入队
dist[x1][y1] = 0; // 起点代价 0
while (q.size()) {
auto [x, y] = q.front(); q.pop_front(); // 取出当前最小代价节点
if (x == x2 && y == y2) return dist[x][y]; // 到达终点,立即返回最短路
for (int k = 0; k < 4; k++) { // 四方向扩展
int nx = x + dx[k], ny = y + dy[k]; // 邻居坐标
if (nx < 1 || nx > n || ny < 1 || ny > m) continue; // 越界剪枝
if (dist[nx][ny] != -1) continue; // 已访问剪枝
int w = (g[nx][ny] == g[x][y] ? 0 : 1); // 边权:相同 0,不同 1
dist[nx][ny] = dist[x][y] + w; // 更新邻居距离
if (w == 0) q.push_front({nx, ny}); // 0 权边插队头
else q.push_back({nx, ny}); // 1 权边排队尾
}
}
return -1; // 无法到达终点
}
常见应用对照表
| 问题 | 关键词 | 算法 |
|---|---|---|
| 迷宫最短路 | 边权1 | 单源BFS |
| 矩阵多起点 | 多源最短路 | 多源BFS |
| 走到相邻格代价0/1 | 0-1边权 | 01-BFS |
| 层次遍历,联通块 | 层序扩散 | BFS |