搜索与图论第二期 BFS


前言

BFS跟DFS同样重要,也一定要熟练的掌握!!!

一、BFS的基本内容

BFS是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。
如果所有节点均被访问,则算法中止。
BFS同样属于盲目搜索。
一般用队列数据结构来辅助实现BFS算法。

算法步骤:

1首先将根节点放入队列中。
2从队列中取出第一个节点,并检验它是否为目标。如果找到目标,则结束搜寻并回传结果。否则将它所有尚未检验过的直接子节点加入队列中。
3若队列为空,表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传“找不到目标”。
重复步骤2。

模板:

 
记录head节点为已经访问;
q.push(head);
 
while (q.empty()) { //当队列q不为空,则继续遍历
    xxx tmp = q.front(); //取出队列q的首数据
    q.pop();
 
    //判断 tmp 节点是否为终点
    if (tmp为目标状态) {
        输出记录,结束遍历
    } else {
        按照题目要求,生成下一步节点next
        if (判断 next 的合法性) {
            记录next节点为已经访问;
            q.push(next);//将合法节点推入到队列中
        }
    }
}

二、典型例题

1.八数码:

搜索与图论第二期 BFS_第1张图片

AC代码:

#include 
#include 
#include 
#include //哈希表存所有距离
#include 
using namespace std;

int bfs(string start) {
	string end = "12345678x";//终点
	queueq;//宽搜队列
	unordered_mapd;//距离数组,到开始的距离
	q.push(start);//先把start放队列里去
	d[start] = 0;
	int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};//上下左右四个数相对于x的位置
	while (q.size()) {//宽搜过程
		auto t = q.front();
		q.pop();
		int distance = d[t];
		if (t == end)//t是终点
			return distance;//返回距离

		//状态转移
		int k = t.find('x');//k来存储x的位置,find返回x的下标
		int x = k / 3, y = k % 3; //把一维数组的下标转化成二维数组的下标
		for (int i = 0; i < 4; i++) {
//x,y是当前'x'的位置,a,b是移动一次之后'x'的位置
			int a = x + dx[i], b = y + dy[i];
			if (a >= 0 && a < 3 && b >= 0 && b < 3) {//a,b都没有出界
				//二维数组的下标a,b对应到一维数组的下标a*3+b
				swap(t[k], t[a * 3 + b]);//状态更新
				//如果更新完之后的t之前没有搜过的话,就说明找到了一个新的状态
				if (!d.count(t)) {
					d[t] = distance + 1;//新的状态的距离更新
					q.push(t);//把新的状态加到队列里
				}
				swap(t[k], t[a * 3 + b]);//恢复状态
			}
		}
	}
	return -1;//如果在宽搜的过程中没有找到,终点返回-1
}

int main() {
	string start;//start存初始状态
	for (int i = 0; i < 9; i++) {
		char c;
		cin >> c;
		start += c;
	}
	cout << bfs(start) << endl;
	return 0;
}

总结

BFS十分重要希望我们都能够熟练的掌握,感谢大家的观看!!!

你可能感兴趣的:(搜索与图论,宽度优先,算法)