- 双向bfs适用于知道起点和终点的状态下使用,从起点和终点两个方向开始进行搜索,可以非常大的提高单个bfs的搜索效率
- 同样,实现也是通过队列的方式,可以设置两个队列,一个队列保存从起点开始搜索的状态,另一个队列用来保存从终点开始搜索的状态,如果某一个状态下出现相交的情况,那么就出现了答案
用一张图来进行说明
当两种颜色相遇的时候,说明两个方向的搜索树遇到一起,这个时候就搜到了答案。
例题1:走迷宫
问题描述:
一个迷宫由 R R R行 C C C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。
给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
输入
第一行是两个整数, R R R和 C C C,代表迷宫的长和宽。 ( 1 ≤ R , C ≤ 40 ) ( 1≤ R,C ≤ 40) (1≤R,C≤40)
接下来是 R R R行,每行 C C C个字符,代表整个迷宫。
空地格子用‘.’表示,有障碍物的格子用‘#’表示。
迷宫左上角和右下角都是‘.’。
输出
输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括起点和终点。
样例输入
5 5
..###
#....
#.#.#
#.#.#
#.#..
样例输出
9
代码如下:
#include <iostream>
#include <queue>
using namespace std;
int r, c;
const int N = 45;
char mp[N][N];
typedef pair<int, int>PII;
#define x first
#define y second
int vis[N][N];
int flag;
int dis[N][N];
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};int dbfs() {queue<PII>q1, q2;//q1为从前往后搜,q2为从后往前搜dis[1][1] = 1;dis[r][c] = 1;vis[1][1] = 1;//q1标记为1vis[r][c] = 2;//q2标记为2//如果某状态下,当前节点和准备扩展节点的状态相加为3,//说明相遇q1.push({1, 1});q2.push({r, c});PII t;while (q1.size() && q2.size()) {if (q1.size() < q2.size()) {每次扩展搜索树小的队列 flag=1表示从前往后搜的队列,flag=0表示从后往前搜的队列t = q1.front();q1.pop();flag = 1;//q1标记为1} else {t = q2.front();q2.pop();flag = 0;//q2标记为0}for (int i = 0; i < 4; i++) {int xx = t.x + dx[i];int yy = t.y + dy[i];if (xx >= 1 && xx <= r && yy >= 1 && yy <= c && mp[xx][yy] == '.')if (!dis[xx][yy])if (flag) {vis[xx][yy] = 1;dis[xx][yy] = dis[t.x][t.y] + 1;q1.push({xx, yy});} else {vis[xx][yy] = 2;dis[xx][yy] = dis[t.x][t.y] + 1;q2.push({xx, yy});} else {if (vis[xx][yy] + vis[t.x][t.y] == 3)//相遇 {return dis[xx][yy] + dis[t.x][t.y];}}}}return -1;
}int main() {cin >> r >> c;for (int i = 1; i <= r; i++)for (int j = 1; j <= c; j++)cin >> mp[i][j];cout << dbfs() << endl;return 0;
}
参考文章链接:https://blog.csdn.net/weixin_43501684/article/details/90147421