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;
}