广度优先搜索——BFS遍历
2017-02-12 20:53
519 查看
广度优先搜索(Breadth First Search , BFS)是一个分层搜索的过程,没有回退过程,是非递归的。
为避免重复访问,需要一个状态数组visited
来存储各顶点的访问状态。为实现逐层访问,bfs算法在实现时需要一个队列,以记忆正在访问的这一层和上一层的顶点,以便于向下一层访问。
例题(1):营救(rescue)
输入描述:"." :道路 "r" :Angle的朋友 "#" :墙壁 "x" :警卫
分析:本题要求从r位置出发到达Angel所在的位置且所需时间最少,适合bfs求解。但在本题中,步数最少的解不一定是最优解。
为求出最优解,采用如下的思路进行bfs搜索。
(1)将Angel的朋友到达某个方格的状态用一个结构体point表示,该结构体包含了Angel的朋友到达该方格时所走过的步数及所花费的时间;在bfs搜索中,队列中的结点是point型数据.
(2)定义一个二维数组mintime,mintime[i][j]表示Angel的朋友走到(i,j)位置所需的最少时间;在bfs搜索过程中,从当前位置走到相邻的位置(x,y)时,只有当该种走法比走到(x,y)所需的时间更少时,才会把当前走到(x,y)位置的状态入队列,否则是不会入队列的。
(3)不能一判断出到达目标位置就退出bfs过程,否则求出的最小时间仅仅是从r到达a最小步数的若干方案中的最小时间,不一定是最优解,一定要等到队列为空,才能得出结论。
另外在题目中未使用visited
数组,因为只有当下一个位置比上一个所需的时间少才能入队列,所以到达(x,y)的最少时间肯定是有下界的。
(1)若用邻接表存储图
(2)用邻接矩阵存储图
为避免重复访问,需要一个状态数组visited
来存储各顶点的访问状态。为实现逐层访问,bfs算法在实现时需要一个队列,以记忆正在访问的这一层和上一层的顶点,以便于向下一层访问。
例题(1):营救(rescue)
输入描述:"." :道路 "r" :Angle的朋友 "#" :墙壁 "x" :警卫
分析:本题要求从r位置出发到达Angel所在的位置且所需时间最少,适合bfs求解。但在本题中,步数最少的解不一定是最优解。
为求出最优解,采用如下的思路进行bfs搜索。
(1)将Angel的朋友到达某个方格的状态用一个结构体point表示,该结构体包含了Angel的朋友到达该方格时所走过的步数及所花费的时间;在bfs搜索中,队列中的结点是point型数据.
(2)定义一个二维数组mintime,mintime[i][j]表示Angel的朋友走到(i,j)位置所需的最少时间;在bfs搜索过程中,从当前位置走到相邻的位置(x,y)时,只有当该种走法比走到(x,y)所需的时间更少时,才会把当前走到(x,y)位置的状态入队列,否则是不会入队列的。
(3)不能一判断出到达目标位置就退出bfs过程,否则求出的最小时间仅仅是从r到达a最小步数的若干方案中的最小时间,不一定是最优解,一定要等到队列为空,才能得出结论。
另外在题目中未使用visited
数组,因为只有当下一个位置比上一个所需的时间少才能入队列,所以到达(x,y)的最少时间肯定是有下界的。
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #define maxint 0x3f3f3f3f #define MAXN 200 using namespace std; struct point { int x,y; int step; int time; }; queue<point>Q; int n,m; char map[MAXN][MAXN]; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; int mintime[MAXN][MAXN]; int ax,ay;///Angel所在的位置 int bfs(point s); int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { memset(mintime,maxint,sizeof(mintime)); memset(map,0,sizeof(map)); for(i=0;i<n;i++) scanf("%s",map[i]); int sx,sy; point start; for(i=0;i<n;i++) for(j=0;j<m;j++) { if(map[i][j]=='a'){ax=i,ay=j;} else if(map[i][j]=='r'){sx=i,sy=j;} } start.x=sx; start.y=sy; start.step=0; start.time=0; mintime[sx][sy]=0; int mint=bfs(start); if(mint<maxint) printf("%d\n",mint); else printf("can not arrived\n"); } return 0; } int bfs(point s) { int i,j; Q.push(s); point hd;///队列头的位置 while(!Q.empty()) { hd=Q.front(); Q.pop(); for(i=0;i<4;i++) { int x=hd.x+dir[i][0]; int y=hd.y+dir[i][1]; if(x>=0&&y>=0&&x<=n-1&&y 4000 <=m-1&&map[x][y]!='#') { point t; t.x=x; t.y=y; t.step=hd.step+1; t.time=hd.time+1; if(map[x][y]=='x') t.time++;///杀死警卫的时间 ///如果比最少时间少,则将t入队列 if(t.time<mintime[x][y]) { mintime[x][y]=t.time; Q.push(t); } } } } return mintime[ax][ay]; }广度优先搜索的伪代码
(1)若用邻接表存储图
dfs(顶点i) { visited[i]=1; 将顶点i入队列; while(队列不为空) { 取出队列头的顶点,设为k; p=顶点k的边链表表头指针; while(p不为空) { ///设指针p指向的边结点所表示的边的另一个顶点为j; if(顶点j未访问过) { 将顶点j标记为访问; 将顶点j入队列; } p=p->next; } } }
(2)用邻接矩阵存储图
dfs(顶点i) { visited[i]=1; 将顶点i入队列; while(队列不为空) { 取出队列头的顶点,设为k; for(j=0;j<n;j++) { ///j是k的邻接点,且未被访问过 if(map[k][j]==1&&!visited[j]) { 将顶点j标记为访问; 将顶点j入队列; } } } }
相关文章推荐
- 广度优先遍历(搜索)(BFS)
- [SDUT](2141)数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 ---BFS(图)
- 广度优先搜索BFS 之图的构造及遍历
- java学习笔记之图的遍历(广度优先搜索BFS)
- bfs广度优先搜索对于图的遍历顺序
- BFS(广度优先遍历搜索解析)
- 数据结构之 图论---基于邻接矩阵的广度优先搜索遍历(输出bfs遍历序列)
- (BFS)广度优先搜索例子:迷宫,寻找连块数
- BFS-迷宫问题-用宽度(广度)优先搜索解决最优路径问题
- 广度/宽度优先搜索(BFS)
- bfs 广度优先搜索
- 邻接表实现--图的深度优先遍历DFS和广度优先遍历BFS
- 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历
- 图的深度优先遍历DFS和广度优先遍历BFS
- 数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
- leetcode 752. Open the Lock 开锁 + 十分典型的广度优先遍历BFS
- Java实现利用广度优先遍历(BFS)计算最短路径的方法
- SDUT OJ数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
- [SDUT](3468)广度优先搜索练习之神奇的电梯 ---BFS(图)
- 数据结 dd3a 构实验之图论一:基于邻接矩阵的广度优先搜索遍历