简单易懂BFS

版权声明:本文为博主原创文章,转载请注明出处-- https://blog.csdn.net/qq_38790716/article/details/88066062

广度优先搜索,又称宽度优先搜索,简称 b f s bfs 。与深度优先搜索不同的是,广度优先搜索会先将与起始距离较近的点搜索完毕,再继续搜索较远的点,而深搜却是沿一个分支搜到最后

b f s bfs 从起点开始,优先搜索离起点最近的点,然后由这个最近的点扩展其他稍近的点,这样一层一层的扩展,就像水波扩散一样。

b f s bfs 需要借助队列来实现:

  • 1.初始的时候把起始点放入队列中,并标记起点访问
  • 2.如果队列不为空,从队列中取出一个元素 x x ,否则算法结束
  • 3.访问和 x x 相连的所有点 v v ,如果 v v 没有被访问,把 v v 入队,并标记已经访问
  • 4.重复执行步骤2

根据该思路可以得出一个简单的代码框架:

void bfs(起始点) {
	将起始点放入队列中;
	标记起点访问;
	while (如果队列不为空) {
		访问队列中队首元素x;
		删除队首元素;
		for (x 所有相邻点) {
			if (该点未被访问过且合法) {
				将该点加入队列末尾;
			}
		}
	}
	队列为空,广搜结束;
}

关于前面所提到的迷宫最短路问题,我们已经学会了使用dfs来求解。用dfs求解迷宫最短路有一个很大的缺点,需要枚举所有可能的路径,读入的地图一旦很大,可能的搜索方案数量就会非常多,用dfs搜索显然效率会非常低。

我们可以借助bfs来求解迷宫游戏。由于bfs是分层搜索,因此,第一次搜索到终点的时候,当前搜索的层数就是最短路径的长度

例1:题目: 迷宫游戏 我们用一个二维的字符数组来表示前面画出的迷宫:

S**. 
....
***T 

其中字符 S S 表示起点,字符 T T 表示终点,字符 表示墙壁,字符 . . 表示平地。你需要从 S S 出发走到 T T ,每次只能向上下左右相邻的位置移动,不能走出地图,也不能穿过墙壁,每个点只能通过一次。你需要编程来求解出从起点到终点的最短路径

由于bfs求解要用到队列,所有我们将点的位置设为一个结构体,方便队列存放:

struct node {
	int x, y, d;
	node (int xx, int yy, int dd) {
		x = xx;
		y = yy;
		d = dd;
	}
};

然后套用上述的bfs框架:

int bfs(int sx, int sy) {
	//将起始点放入队列中;
	queue<node> q;
	q.push(node(sx, sy, 0));
	//标记起点访问;
	vis[sx][sy] = true;
	while (!q.empty()){
		//访问队列中队首元素x;
		node now = q.front();
		//删除队首元素;
		q.pop();
		for (int i = 0; i < 4; ++i) {
			int tx = now.x + dir[i][0];
			int ty = now.y + dir[i][1];
			//该点未被访问过且合法
			if (in(tx, ty) && maze[tx][ty] != '*' && !vis[tx][ty]) {
				if (maze[tx][ty] == 'T') {
					return now.d + 1;
				} else {
					//将该点加入队列末尾;
					vis[tx][ty] = true;
					q.push(node(tx, ty, now.d + 1));
				}
			}
		}
	}
	return -1;
} 

完整实现:

#include <iostream>
#include <string>
#include <queue>
using namespace std;
int n,m;
string maze[110];
bool vis[110][110];
int dir[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
bool in(int x, int y) {
	return 0 <= x && x < n && 0 <= y && y < m;
}
struct node {
	int x, y, d;
	node (int xx, int yy, int dd) {
		x = xx;
		y = yy;
		d = dd;
	}
};

int bfs(int sx, int sy) {
	queue<node> q;
	q.push(node(sx, sy, 0));
	vis[sx][sy] = true;
	while (!q.empty()){
		node now = q.front();
		q.pop();
		for (int i = 0; i < 4; ++i) {
			int tx = now.x + dir[i][0];
			int ty = now.y + dir[i][1];
			if (in(tx, ty) && maze[tx][ty] != '*' && !vis[tx][ty]) {
				if (maze[tx][ty] == 'T') {
					return now.d + 1;
				} else {
					vis[tx][ty] = true;
					q.push(node(tx, ty, now.d + 1));
				}
			}
		}
	}
	return -1;
} 
int main() {
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		cin >> maze[i];
	}
	int x, y;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			if (maze[i][j] == 'S') {
				x = i;
				y = j;
			}
		}
	}
	cout << bfs(x, y);
	return 0;
}

i n p u t input :

5 6
…S*
.
..
*…
.
.T…

o u t p u t output :

7

猜你喜欢

转载自blog.csdn.net/qq_38790716/article/details/88066062