这里要介绍的广度优先搜索也是搜索算法的一种,但是这个和刚刚讲到的深度优先搜索有点不一样的地方在于,深度优先搜索是一次走到底,撞了南墙才回头,而广度优先搜索是每次每个方向都走一步,然后保存起来以便之后在此基础上走。
所以这里很必要的是定义一个新的数据结构,通常是pair来存储当前问题空间的状态,然后把每一步的状态存到队列中,每次就按顺序出队即可。
然后我们先上一道关于BFS的移到非常经典的栗子:
845. 八数码 - AcWing题库
代码:
#include
using namespace std;
queue
unordered_map
int fs[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
int bfs(string start){
q.push(start);
mp[start] = 0;
string end = "12345678x" ;
while(!q.empty()){
string t = q.front();
q.pop();
if(t == end){
return mp[t];
} //边界条件
int dist = mp[t];
int k = t.find('x');
int a = k/3 , b = k%3;
for(int i = 0; i<4;i++){
int aa = a+fs[i][0];
int bb = b+fs[i][1];
if(aa>=0 && aa<3 && bb >=0 && bb<3){
swap(t[k],t[aa*3+bb]);
if(!mp.count(t)){
q.push(t);
mp[t] = dist+1;
}
swap(t[k],t[aa*3+bb]);
}
}
}
return -1;
}
int main()
{
string start;
for(int i = 0;i<9;i++){
char c;
cin>>c;
start += c;
}
cout<
return 0;
}
分析:这里我们就是把初始状态输入进去,然后往每一个可以走的方向都去走向一步,直到发现走到目标位置后退出;
缺点:对于空间的要求比较高,因为往往是成指数函数的趋势存储新的状态,一旦目标节点所在层数过深就会MLE;
优点:时间要求不高,而且可以求出最短路,而DFS只能判断是否存在路!
深搜和广搜的一些共同之处:
基本的DFS和BFS的函数我们都可以写成以下格式:
##############if(边界条件){
***********return ;******
}
for(循环条件){
####判断可行性###
####走下一步,使新状态入队####
}
剪枝:
·可行性剪枝,如果搜索到某一个位置的时候我们发现此时已经不满足条件(跑出了地图,消耗的时间已经超过要求......),我们就要及时放弃!
·最优性剪枝:如果搜索到一个位置时,此时我们所观测的那个Key Number已经不如当前存在的最优了,我们也要及时放弃!