BFS(广度优先搜索)
最简单的搜索包含 DFS 和 BFS,他们分别有着下面不同的用途和区别:
区别于用途:
1.BFS是用来搜索最短径路的解是比较合适的,比如求最少步数的解,最少交换次数的解,因为BFS搜索过程中遇到的解一定是离根最近的,所以遇到一个解,一定就是最优解,此时搜索算法可以终止。这个时候不适宜使用DFS,因为DFS搜索到的解不一定是离根最近的,只有全局搜索完毕,才能从所有解中找出离根的最近的解。(当然这个DFS的不足,可以使用迭代加深搜索ID-DFS去弥补)
2.空间优劣上,DFS是有优势的,DFS不需要保存搜索过程中的状态,而BFS在搜索过程中需要保存搜索过的状态,而且一般情况需要一个队列来记录。
3.DFS适合搜索全部的解,因为要搜索全部的解,那么BFS搜索过程中,遇到离根最近的解,并没有什么用,也必须遍历完整棵搜索树,DFS搜索也会搜索全部,但是相比DFS不用记录过多信息,所以搜素全部解的问题,DFS显然更加合适。
下面是广度优先搜索的基本思想与模板
BFS用到了队列的一些操作,其基本思想步骤是:
1.首先将根节点放入队列中。
2.从队列中取出第一个节点,并检验它是否为目标。
3.如果找到目标,则结束搜索并回传结果。否则将它所有尚未检验过的直接子节点加入队列中。若队列为空,表示整张图都检查过了——亦即图中没有欲搜索的目标。结束搜索并回传“找不到目标”。
4.重复步骤2。
其基本模板如下:
初始化队列Q
Q={起点s};
标记s为已访问
while(!Q.empty())
{
去Q队首元素U;
u出队;
if(u==目标状态){...}
所有与u相邻且未访问过的点进入队列;(可以通过设一个方向数组for一遍实现)
标记U为已访问;
}
一个完整的程序如下:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=2e5+5;
int v[maxn];
int n,k,t,ans[maxn];
queue<int> q;
void bfs(int start,int last)
{
q.push(start);
int fi,ne;
ans[start]=0;
v[start]=1;
while(!q.empty())
{
fi=q.front();
q.pop();
for(int i=0; i<3; ++i)
{
if(0==i) ne=fi-1;
else if(1==i) ne=fi+1;
else if(2==i) ne=fi*2;
if(ne<0||ne>maxn) continue;
if(!v[ne]){
q.push(ne);
v[ne]=1;
ans[ne]=ans[fi]+1;
}
if(ne==last) break;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
memset(v,0,sizeof(v));
memset(ans,0,sizeof(ans));
bfs(n,k);
n>=k?cout<<n-k<<endl:cout<<ans[k]<<endl;
return 0;
}