BFS速成
我是个标题党,哪有什么速成,没有时间的积累是不可能成的。
但是这篇博客可以帮助刚刚入门的朋友们,初步了解BFS。(因为我也是最近才开始去慢慢深入了解BFS的,讲的不会太晦涩)
首先我们了解一下BFS是怎么运作的。
本人的疏漏 这里的 3号点应该是 2
我们开始的起始点是1-1 五角星处,开始搜索。BFS是按层搜索,先把我标记的①处搜索完,顺序无所谓,看你的搜索方向。
我们搜索完
后就要入队。 假设开始队列: queue:(☆,1-1)
搜索第一层后 queue:(①,1-2),(①,2-2),(①,2-1) 我们在搜索之前就要将第0层的出队 也就是五角星。
接下来第二层 queue:(①,2-2),(①,2-1),(②,1-3)
queue:(①,2-1),(②,1-3),(②,2-3),(②,3-2) 这里注意一下,当我们搜索(①,2-2)他的周围有两个②没有被搜索过,所以这里要入队两个。
queue:(②,1-3),(②,2-3),(②,3-2),(②,3-1)现在第二层也搜索完了,接下来都是一样的搜索过程。
下面我们直接看代码吧
typedef struct node
{
int x,y;
int time;//权值,看题目而定
} node;//这个是我们队列的结构体
char Map[M][M];//地图建立
int vis[M][M];//检查数组
int n,m;//图的大小,n行,m列
queue<node> q;//建立队列
int dx[8]= {1,0,-1,0,1,-1,-1,1},dy[8]= {0,1,0,-1,1,1,-1,-1};//这个是我们的移动数组,这个数组决定了我们的搜索过程。
BFS
int bfs(int sx,int sy)
{
if(!q.empty()) q.pop();//将队列清空
node t,nt;
t.x=sx,t.y=sy;
vis[sx][sy]=1;
q.push(t);
while(!q.empty())
{
t=q.front();//t为当前的结构体,里面的内容为x,y,cost。横坐标,纵坐标和权值
q.pop();
int nx,ny,i,j,k;
for(k=0; k<8; k++)//这里就是按照走法将当前位置能走到的点全部试一次
{
nx=t.x+dx[k];
ny=t.y+dy[k];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&vis[nx][ny]==0&&Map[nx][ny]=='@')//假设没有越界,且没有被访问
{
nt.x=nx;
nt.y=ny;
vis[nx][ny]=1;//表示已经访问过
q.push(nt);//新的结点入队
}
}
}
}
BFS到这里已经讲得差不多了
还有一个地方要讲的就是优先队列。
怎么把优先队列和BFS结合起来。有的题目是要求你求出最小的步数,或者耗时最少,这时候就要用到优先队列了。
优先队列的意思就是 将优先程度大的先出队,也就是允许病人急插队,而不是按照先进先出的原则。
优先队列我这里涉及到了运算符重载
typedef struct Node
{
int x,y,time;
bool operator <(const Node &p) const//这里是重载的小于号
{
return time>p.time;//这里的意思就是time大的 优先级小,往后靠,比优先级大的后出队
}
} Node;
priority_queue<Node> q;//这个队列就是优先队列
想更深入了解优先队列的朋友https://blog.csdn.net/c20182030/article/details/70757660
最后呢奉上几道BFS入门 ZOJ-1709 POJ-3126 HDU-2717
BFS+优先队列 HDU-1008 (诡异的楼梯)