一.简介
bfs是一种图搜索算法,用于在图或树等数据结构中遍历或搜索节点。属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。
二.作用
常用来搜索最短路径。
三.bfs搜索步骤
1.创建一个存储图(示例坐标)a[][]。
b[][]用来标记位置(标记过的位置不在遍历)。
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
存储向四个方向遍历的运算坐标(0,1),(1,0),(0,-1),(-1,0);
typedef pair<int,int> pll;(可以存储一组坐标,也可用结构体)
queue<pll>q;(这里需要一个队列,利用队列先进先出的特性)。
q.push({x1,y1}); b[x1][y1]=0;//标记起始位置;
while(!q.empty())//判断容器是否为空;
在循环中执行pll p=q.front();用p<int ,int>存储q中的第一对数;
q.pop();//存储后,出队。
对p<int ,int>中的坐标进行四个方向遍历(红色区域跳过,即a[4][2],a[4][4]=false)
if(a[x][y]=false)contiue; if(b[x][y]>0)continue;标记过的跳过。
1,1 | 2 | 3 | 4 | 5 |
2 | x-1,y不变 | |||
3 | x不变y-1 | 起点b[3][3]=0 | x不变y+1 | |
4 | ———— | x+1,y不变b[4][3]=b[3][3]+1 | ———— | |
5 | b[5][3]=b[4][3]+1 | 终点③ b[5][4]=b[5][3]+1 |
将遍历的方向坐标入栈,并用b[][]标记坐标.例b[x][y]=1;
if(x==x2&&y==y2)cout<<b[x][y]<<endl;判断是否找到终点坐标,
找到,输出停止循环。否则继续循环,以其中一个点(x+1,y不变即(4,3))为例,对坐标进行四个方向遍历(4,4)跳过,(5,3)入栈,用b[5][3]=b[5][4]++标记(4,2)跳过,(3,3)跳过。
继续循环,对(5,3)方向遍历,(5,4)入栈,b[5][4]=b[5][3]+1;if(x==x2&&y==y2)cout<<b[x][y]<<endl;找到终点坐标,
四.题码展示
题目描述
爱与愁大神买完东西后,打算坐车离开中山路。现在爱与愁大神在 x1,y1 处,车站在 x2,y2 处。现在给出一个 n×n(n≤1000) 的地图,0 表示马路,1 表示店铺(不能从店铺穿过),爱与愁大神只能垂直或水平着在马路上行进。爱与愁大神为了节省时间,他要求最短到达目的地距离(每两个相邻坐标间距离为 1)。你能帮他解决吗?
输入格式
第 1 行包含一个数 n。
第 2 行到第 n+1 行:整个地图描述(0 表示马路,1 表示店铺,注意两个数之间没有空格)。
第 n+2 行:四个数 x1,y1,x2,y2。
输出格式
只有 11 行,即最短到达目的地距离。
输入输出样例
输入 输出
3 4 001 101 100 1 1 3 3
代码展示:
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
void bfs(int ,int);
int x1,y1,x2,y2,n,x,y;
char a[1010][1010];
int b[1010][1010];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
typedef pair<int,int> pll;
queue<pll>q;
int main()
{
memset(b,-1,sizeof b);
cin>>n;
for(int i=1;i<=n;i++)
scanf("%s",a[i]+1);//+1指向第二行第二列。
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
bfs(x1,y1);
return 0;
}
void bfs(int x1,int y1)
{
q.push({x1,y1});
b[x1][y1]=0;//标记起始位置;
while(!q.empty())//判断容器是否为空;
{
pll p=q.front();用p<int ,int>存储q中的第一对数;
q.pop();//存储后,出队。
for(int i=0;i<4;i++)//对存储的坐标进行操作
{
x=p.first+dx[i];//四个方向进行遍历;
y=p.second+dy[i];
if(b[x][y]>=0)continue;//标记过则跳过
if(a[x][y]=='1')continue;//测试数据(避开点)
if(x<1||x>n||y<1||y>n)continue;//出界跳过
b[x][y]=b[p.first][p.second]+1;//次数累加
q.push({x,y});//将得到的新坐标入队。
if(x==x2&&y==y2)cout<<b[x][y]<<endl;
}
}
}