BFS介绍:
已知图G=(V,E)和一个源顶点s,宽度优先搜索以一种系统的方式探寻G的边,从而“发现”s所能到达的所有顶点,并计算s到所有这些顶点的距离(最少边数),该算法同时能生成一棵根为s且包括所有可达顶点的宽度优先树。对从s可达的任意顶点v,宽度优先树中从s到v的路径对应于图G中从s到v的最短路径,即包含最小边数的路径。该算法对有向图和无向图同样适用。
BFS特点:
算法自始至终一直通过已找到和未找到顶点之间的边界向外扩展,就是说,算法首先搜索和s距离为k的所有顶点,然后再去搜索和S距离为k+l的其他顶点
用颜色解释BFS:
为了保持搜索的轨迹,宽度优先搜索为每个顶点着色:白色(非灰且非黑即为白)、灰色(墙 / 不可到达点)或黑色(可到达点)。算法开始前所有顶点都是白色,随着搜索的进行,各顶点会逐渐变成灰色,然后成为黑色。在搜索中第一次碰到一顶点时,我们说该顶点被发现,此时该顶点变为非白色顶点。因此,灰色和黑色顶点都已被发现,但是,宽度优先搜索算法对它们加以区分以保证搜索以宽度优先的方式执行。若(u,v)∈E且顶点u为黑色,那么顶点v要么是灰色,要么是黑色,就是说,所有和黑色顶点邻接的顶点都已被发现。灰色顶点可以与一些白色顶点相邻接,它们代表着已找到和未找到顶点之间的边界。
模板题:
代码:
#include<bits/stdc++.h>
using namespace std;
int s, t, n, m;
int mp[510][510];
int dis[510][510];
int dir[4][2] ={{1,0},{-1,0},{0,-1},{0,1}};//方向数组
queue<int> q;
int bfs(int s, int t)
{
while (!q.empty()) q.pop();//清空队列
q.push(s);
while (!q.empty())
{
int tmp = q.front();
q.pop();
int x = tmp / m,y = tmp % m;//小技巧
for (int i = 0; i < 4; i++)
{
int dx = x+dir[i][0];
int dy = y+dir[i][1];
if (dx < 0 || dy < 0 || dx >= n || dy >= m) continue;//迷宫边界
if(mp[dx][dy] == 0) continue;//障碍物
if (dis[dx][dy] != 0) continue;//重复点
if (dx*m+dy == t) return 1;
dis[dx][dy] = dis[x][y] + 1;//记录起点到达每个所能到达的点的距离
q.push(dx*m+dy);
}
}
return 0;
}
int main()
{
while(scanf("%d%d", &n,&m) != EOF)
{
memset(mp, 0, sizeof(mp));
memset(dis, 0, sizeof(dis));
for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)
{
char c;
scanf(" %c", &c);//空格可以消去所有空格和回车
if (c == 'S') {s = i*m+j; mp[i][j] =1;}
else if (c == 'E') {t = i*m+j; mp[i][j] =1;}
else if (c == '.') {mp[i][j] = 1;}
else if (c == '#') {mp[i][j] = 0;}
}
if (bfs(s, t)) printf("Yes\n");
else printf("No\n");
}
return 0;
}