同步发表于cnblog。
B F S \tt BFS BFS 的定义与思想
B F S \tt BFS BFS,学名 B r e a d t h F i r s t S e a r c h \mathtt{Breadth\ First\ Search} Breadth First Search,中文名“广度优先搜索”,是一类研究最短路径的算法。
一旦你看到一个题目是求到一个点的最短路径,那么它大概率是 B F S \tt BFS BFS。
当我们投一个石子时,水上的涟漪就会一圈一圈的扩散开
而广度优先搜索正是如此实现的:
他像一层波浪,一次搜索“一层”的内容,然后检查每一层中有没有答案,如果有,那么就输出步数。
B F S \tt BFS BFS 算法思想与实现
算法思想
从起点 ( s x , s y ) (sx,sy) (sx,sy) 开始,每次搜一层,如果当前能走且没有走过,那么就到达这一点,更新位置,步数加一。
接下来就是代码实现:
基本定义
- B F S \tt BFS BFS 不能重复走,需要一个标记数组 v i s \tt vis vis。
- 一次可以往 4 4 4 个方向走,要两个方向数组,处理 x x x 轴和 y y y 轴。
- 定义一个结构体 n o d e \tt node node,带三个参数 x , y , s t e p x,y,step x,y,step,表示当前在 ( x , y ) (x,y) (x,y),走了 s t e p step step 步。
- 每次 B F S \tt BFS BFS 都要一个队列,记录当前走的点,走到了就弹出。
- 每次都要记录 n x , n y nx,ny nx,ny,表示走到 ( n x , n y ) (nx,ny) (nx,ny)。
代码实现
初始化:
- 我们现将当前表记走没走过的 v i s vis vis 数组清零,防止数据覆盖
- 定义一个 n o d e node node 类型 c u r cur cur 为当前的起点,将当前的起点 ( s x , s y ) (sx,sy) (sx,sy) 标记到数组 v i s vis vis 里。
- 将 c u r cur cur 入队。
开始搜索:
- 进行
while
循环,条件式q.empty()==0
(当前“一层”还没走完) - 将
c
u
r
cur
cur 为当前的点(
cur=q.front()
),弹出当前元素,因为已经走到。 - 检查,如果当前已经走到终点,那么就直接返回当前元素 c u r cur cur 的步数 s t e p step step。
- 开始 f o r \tt for for 循环,走到 4 4 4 个方向,注意边界条件,不能越界,不是障碍物,不能走过。
下面以这个题为例:
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
下面附上代码:
#include <bits/stdc++.h>
using namespace std;
int r, c;
bool vis[1005][1005];
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
char a[1005][1005];
struct node {
int x, y, step;
};
int bfs(int sx, int sy)
{
memset(vis, 0, sizeof(vis));
queue<node> q;
node cur = {sx, sy, 1};
vis[sx][sy] = true;
q.push(cur);
while(!q.empty())
{
cur = q.front();
q.pop();
if (cur.x == r && cur.y == c)
{
return cur.step;
}
for(int i = 0; i < 4; i++)
{
int nx = dx[i] + cur.x;
int ny = dy[i] + cur.y;
if (nx > 0 && nx <= r && ny > 0 && ny <= c && vis[nx][ny] == false && a[nx][ny] != '#')
{
node nxt = {nx, ny, cur.step + 1};
q.push(nxt);
vis[nx][ny] = true;
}
}
}
return -1;
}
int main()
{
cin >> r >> c;
for (int i = 1 ; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
cin >> a[i][j];
}
}
cout << bfs(1, 1);
return 0;
}
代码中的基本都在上面讲解了,不会的请私信。