農夫知道一頭牛的位置,想要抓住它。農夫和牛都位於數軸上,農夫起始位於點n(0<=n<=100000),牛位於點k(0<=k<=100000)。農夫有兩種移動方式:
1、從x移動到x-1或x+1,每次移動花費一分鐘
2、從x移動到2*x,每次移動花費一分鐘
假設牛沒有意識到農夫的行動,站在原地不動。農夫最少要花多少時間才能抓住牛?
假設農夫起始位於3,牛位於5,如何搜尋一條到5的路徑?
策略一:深度優先搜尋:
從起點出發,隨機挑選乙個方向,能往前走就往前走(擴充套件),走不動了則回溯。
運氣好的話: 3->4->5
運氣最壞的話: 3->2->1->0->4->5
如果想要求最優解,需要遍歷所有走法,但可以使用一定方法進行剪枝。
運算過程中需要儲存路徑上的節點,數量較少,用棧儲存。
策略二:廣度優先搜尋
給節點分層。起點就是第0層,從起點最少需要n步就能到達的點就屬於第n層。
依層次順序,從小到大的擴充套件節點。把層次低的點全部擴充套件出來後,才會擴充套件層次高得點。
搜尋過程:
12 4 6
1 5注意:擴充套件時,不能擴充套件已經走過的節點。可確保找到最優解,但是因擴充套件出 來的節點較多,且多數節點都需要 儲存,因此需要的儲存空間較大。 用佇列存節點。
廣度優先搜尋演算法如下:(用queue )
把初始節點s0放入open表中;
如果open表為空,則問題無解,失敗 退出;
把open表的第乙個節點取出放入 closed表,並記該節點為 n ;
考察節點 n是否為目標節點。若是, 則得到問題的解,成功退出;
若節點 n不可擴充套件,則轉第(2)步;
擴充套件節點 n,將其不在closed表和 open表中的子節點 (判重)放入open表的尾部 ,並為每乙個子節點設定指向父節點的指標 ( 或記錄節點的層次),然後轉第(2)步
**實現如下:
#include
#include
#include
using
namespace std;
int n, k;
const
int maxn =
100000
;int visited[maxn +10]
;//判重標記,為true表示該點已經擴充套件過了
struct step};
queue q;
//佇列,即open表
intmain()
else
if(s.x +
1<= maxn &&
!visited[s.x +1]
)if(s.x *
2<= maxn &&
!visited[s.x *2]
) q.
pop();
}}return0;
}
廣搜一般用於狀態表示比較簡單、求最優策略的問題
缺點:盲目性較大,尤其是當目標節點距初始節點較遠時,將產 生許多無用的節點,因此其搜尋效率較低。
需要儲存所有擴充套件出 的狀態,占用的空間大
深搜幾乎可以用於任何問題
dbfs演算法是對bfs演算法的一種擴充套件。
dbfs演算法相對於bfs演算法來說,由於採用了雙向擴充套件的方式,搜尋樹的寬度得到了明顯的減少,所以在演算法的時間複雜度和空間 複雜度上都有較大的優勢。
int
expand
(i)//其中i為佇列的編號,0或1
廣度優先搜尋1
乙個人站在n點,只能向左走一步,或者向右走一步,或者直接走n的2倍步,要求走最少的步數抓住站在k點的牛。include define max 200005 定義最大值 using namespace std int cnt v 3000000 初始化 void bfs int n,int k 廣搜 ...
搜尋(廣度優先搜尋) BFS 1
廣度優先搜尋 bfs 狀態查詢樹 剪枝 題目1456 勝利大逃亡 題目描述 ignatius被魔王抓走了,有一天魔王出差去了,這可是ignatius逃亡的好機會.魔王住在乙個城堡裡,城堡是乙個a b c的立方體,可以被表示成a個b c的矩陣,剛開始ignatius被關在 0,0,0 的位置,離開城堡...
搜尋 廣度優先搜尋
廣度優先搜尋一層一層地進行遍歷,每層遍歷都是以上一層遍歷的結果作為起點,遍歷乙個距離能訪問到的所有節點。需要注意的是,遍歷過的節點不能再次被遍歷。class solution,int shortestpathbinarymatrix vectorint grid length return 1 cl...