先导知识:
数组、栈、队列、树、图等基本数据结构
图论基本知识
正文:
通过一个小例子,我们来理解BFS的思想。
如上图,这是一棵树,树具有明显的层次关系,我们如果要遍历这棵树,有两种方法可选。
一种就是从1点,选择其中的枝杈,一直遍历到底,如果到底了,我们就回退到上一个节点,选择另一条路径。已经走过的节点我们在地图上标记出来,重复以上的过程,直至遍历过所有的节点为止。
一种可能的路径选择为1->2->5->6->3->7->4->8
这种策略我们一般称为带回溯的深度优先搜索方法(DFS)。
而另一种策略就是,从树的根节点开始,逐层遍历,先从最近的节点开始,一层层遍历,直至遍历到最后一层最后一个节点。
一种可能的路径选择为1->2->3->4->5->6->7->8
注意我们所说的“层”,在空间上是连续的,在遍历的时间中,他们不一定是连续的。
这种策略即是广度优先搜索(BFS)。
一种更直观的理解方式是在网状结构的任意节点(如下图)
可以看到,中部的红色节点逐渐“侵蚀”周围的节点的过程
代码示例:
1 int visited[SIZE][SIZE];//确保每个节点只访问一次,否则会死循环 2 char chestDisk[SIZE][SIZE+2];//要搜索的“图” 3 int dx[] = {0, 0, 1, -1}; 4 int dy[] = {-1, 1, 0, 0};//这两个数组枚举出了该元素与下层元素之间的所有情况 5 bool BFS(int chest, int i, int j){ 6 int x,y; 7 queue<pair<int, int> > que;//使用队列来确保层次 8 que.push(make_pair(i,j));//初始状态入队 9 int count = 0;//可能的控制变量 10 while(!que.empty()){//循环控制条件,队列不为空,队列内部也可有其他终止循环的条件 11 pair<int, int> temp = que.top();//取队首元素 12 que.pop();//出队 13 for(int i = 0;i < 4; i ++){ 14 x = dx[i] + temp.first; 15 y = dy[i] + temp.second; 16 if(0<=x<SIZE&&0<=y<SIZE&&!chestDisk[x][y]!='#'){//该点满足条件 17 if(!visited[i][j]){//该点未访问过 18 visited[x][y] = 1; 19 que.push(make_pair(x,y));//将下一层的点入队 20 count++;//控制变量变化 21 } 22 } 23 24 } 25 } 26 return count>=chest;//返回一个判断条件 27 }
适用范围:
图结构的层次搜索——如寻找迷宫出口
例题:poj1321
对某一对象,寻找与其相似特征的其他对象,最终推演出结果
迭代方式固定,求初始状态经过多少次迭代可以到达目标状态
例题:poj3278