赞
踩
从字面意思上说(比较正规,看看就行):
宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
从图上来看(这个更易于理解):
现在有一棵树(地图),在这个上面我们现在在A点,但如果我们想去G点,那么bfs算法中
要求我们寻找的时候宽度优先即横着找。因此如果要找从A点到G点的最短路径,我们会先找A,当这一行找完之后,再找B点、C点、D点,第二行找完之后,我们接着第三行展开找E点知道找到G点,这是就大功告成了。
但为什么这样找?我们先看一个例子。
走迷宫
给定一个n*m的二维整数数组,用来表示一个迷宫,数组中只包含0或1,其中0表示可以走的路,1表示不可通过的墙壁。
最初,有一个人位于左上角(1, 1)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角(n, m)处,至少需要移动多少次。
数据保证(1, 1)处和(n, m)处的数字为0,且一定至少存在一条通路。
输入格式
第一行包含两个整数n和m。
接下来n行,每行包含m个整数(0或1),表示完整的二维数组迷宫。
输出格式
输出一个整数,表示从左上角移动至右下角的最少移动次数。
数据范围
1≤n,m≤100
1
输入样例:
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
1
2
3
4
5
6
输出样例:
8
我们可以在每次出发的时候,走到离自己最近的点(贪心思想),由此我们每次都保证走最近的,那从局部最近推整体最近,直到走到终点,必有一条路是整体最近的。所以我们可以利用BFS做最短路问题。
在这个迷宫当中,我们要走到(n,m)点的话是不能用dfs广度搜索一条道走到黑的,我们需要稳扎稳打,走一个点记录一个点,只要走到(n,m)点都记录完为止。这就是现在说的bfs算法。
1.待我先解释一下为什么要用队列(用来解决移动到哪个点):
对于上面那个图,我们从A点开始时,让A点入队,对A点附近的点进行查找
之后A点附近搜索完之后,A点出队,让B点、C点、D点入队:
直到最后一直进行这个步骤:
2.上面解决了移动到哪个点的问题,我们接着解决怎么移动的问题:
int dx[4]={0,0,-1,1};//表示要走的四个方向
int dy[4]={1,-1,0,0};
我们使用这两行代码,对于一个点(x,y)坐标表示,如果想向左移动,就是x+(-1),y+0,那么向右就是x+1,y。
这是当我们到达点B后,我们让点B的x、y加上4个不同的移动方向,这时向上走会遇到A点向右走会遇到D点,这样就会把周围点搜索一遍。
注:同时要记得标记一下用过的点,确保不会重复使用。
- for(int i=0;i<4;i++){
- int nex=top.first+dx[i];
- int ney=top.second+dy[i];
- //如果某一个方向的下一个位置没有走过,并且位置为零(即此题中可以通过)
- //记录此点,同时让该点入队,下一次以此点展开搜索
- if(nex>=0&&nex<n&&ney>=0&&ney<m&&mark[nex][ney]==-1&&mp[nex][ney]==0){
- mark[nex][ney]=mark[top.first][top.second]+1;
- q.push({nex,ney});
- }
- }
3.这里我们以上面这道经典题目为例进行代码展示:
- #include<bits/stdc++.h>
- using namespace std;
- int n,m;
- int dx[4]={0,0,-1,1};//表示要走的四个方向
- int dy[4]={1,-1,0,0};
- const int N=110;
- int mp[N][N];//用来存储地图
- int mark[N][N];//表示是否走过当前位置(未走过为-1),以及走了多远
- int ans;
- typedef pair<int,int> PII;
- void bfs(){
- memset(mark,-1,sizeof mark);//都初始化为-1表示没有来过
- queue<PII> q;
- q.push({0,0});//让起点入队
- mark[0][0]=0;
- while(!q.empty()){
- PII top=q.front();//以队列每个元素为起点展开四个方向的搜索
- for(int i=0;i<4;i++){
- int nex=top.first+dx[i];
- int ney=top.second+dy[i];
- //如果某一个方向的下一个位置没有走过,并且位置为零(即此题中可以通过)
- //记录此点,同时让该点入队,下一次以此点展开搜索
- if(nex>=0&&nex<n&&ney>=0&&ney<m&&mark[nex][ney]==-1&&mp[nex][ney]==0){
- mark[nex][ney]=mark[top.first][top.second]+1;
- q.push({nex,ney});
- }
- }
- q.pop();//当这个节点搜索结束则出队
- }
- cout<<mark[n-1][m-1]<<endl;//输出最短路结果
- }
- int main(){
- cin>>n>>m;
- for(int i=0;i<n;i++){
- for(int j=0;j<m;j++){
- cin>>mp[i][j];
- }
- }
- bfs();
- system("pause");
- return 0;
- }
至此,功德圆满
入坑不易,记得轻轻点一下关注哦
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。