- 温张鑫 的博客
七月day4(搜索)
- @ 2025-7-23 21:02:27
BFS
BFS 全称是 Breadth First Search,中文名是广度优先搜索。
是图上最基础、最重要的搜索算法之一。
所谓广度优先。就是每次都尝试访问同一层的节点。 如果同一层都访问完了,再访问下一层。
这样做的结果是,BFS 算法找到的路径是从起点开始的 最短 合法路径。换言之,这条路径所包含的边数最小。
在 BFS 结束时,每个节点都是通过从起点到该点的最短路径访问的。
算法过程可以看做是图上火苗传播的过程:最开始只有起点着火了,在每一时刻,有火的节点都向它相邻的所有节点传播火苗,我们通常用队列来实现。
例题:
#include<bits/stdc++.h>
using namespace std;
int n, m;
int g[110][110], vis[110][110], dist[110][110]; // g存图,vis标记x,y是否走过,dist记录起点到x,y的最短距离
int dx[] = {0,1,0,-1}, dy[] = {1,0,-1,0}; // 方向数组
bool check(int nx, int ny)
{
// 没有越界,没有来过,且不是墙
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny] && g[nx][ny] == 0)
return true;
return false;
}
void bfs()
{
/*
1.起点入队
2.当队列不为空,弹出队头元素,并拓展队头
3.重复2,直到队列为空
4.输出答案
*/
queue<pair<int,int>> q;
q.push({1,1});
vis[1][1] = 1; // 起点标记
dist[1][1] = 0; // 初始化距离
while (q.size())
{
auto t = q.front(); q.pop();
int x = t.first, y = t.second;
if (x == n && y == m) return;
for (int i = 0; i < 4; i++)
{
int nx = x + dx[i], ny = y + dy[i];
if (check(nx, ny))
{
vis[nx][ny] = 1;
q.push({nx, ny});
dist[nx][ny] = dist[x][y] + 1;
}
}
}
}
int main()
{
memset(dist, 0x3f, sizeof dist); // 初始化极大值
cin >> n >> m;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j++)
cin >> g[i][j];
bfs();
cout << dist[n][m];
return 0;
}
DFS
DFS 全称是 Depth First Search,中文名是深度优先搜索,是一种用于遍历或搜索树或图的算法。所谓深度优先,就是说每次都尝试向更深的节点走。
该算法讲解时常常与 BFS 并列,但两者除了都能遍历图的连通块以外,用途完全不同,很少有能混用两种算法的情况。
我们通常用递归和栈来实现。
例题:
#include<bits/stdc++.h>
using namespace std;
int n, m;
int g[110][110], vis[110][110], dist[110][110]; // g存图,vis标记x,y是否走过,dist记录起点到x,y的最短距离
int dx[] = {0,1,0,-1}, dy[] = {1,0,-1,0}; // 方向数组
bool check(int nx, int ny)
{
// 没有越界,没有来过,且不是墙
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny] && g[nx][ny] == 0)
return true;
return false;
}
void dfs(int x, int y)
{
if (x == n && y == m) // 边界判定
{
return;
}
for (int i = 0; i < 4; i++) // 循环4个方向
{
int nx = x + dx[i];
int ny = y + dy[i];
if (check(nx, ny) && dist[x][y] + 1 < dist[nx][ny]) // 可行性判定并进一步搜索
{
vis[nx][ny] = 1; // 标记
dist[nx][ny] = dist[x][y] + 1; // 更新最短路
dfs(nx, ny); // 递归搜索
vis[nx][ny] = 0; // 回溯
}
}
}
int main()
{
memset(dist, 0x3f, sizeof dist); // 初始化极大值
cin >> n >> m;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j++)
cin >> g[i][j];
vis[1][1] = 1; // 起点标记
dist[1][1] = 0; // 初始化距离
dfs(1,1);
cout << dist[n][m];
return 0;
}