BFS 思路加簡單例題

2021-10-24 23:57:20 字數 3436 閱讀 9900

上次講的dfs是一直往前走,直到無路可走的時候就返回,而bfs不一樣。

bfs是廣度優先搜尋,顧名思義就是橫著來搜尋,也就是按層次來搜尋,一層層來搜尋。

廣度優先搜尋是一種分層的查詢過程,每向前走一步可能訪問一批頂點,不像深度優先搜尋(dfs)那樣有回退的情況,因此它不是乙個遞迴的演算法,為了實現逐層的訪問,演算法必須借助乙個輔助佇列並且以非遞迴的形式來實現。

bfs搜尋的步驟

1、首先建立乙個mp[ ]陣列用來判斷該位置是否被訪問;

2、再建立乙個佇列p用來儲存下一步要訪問的點。

3、讓起點start入隊,並使該點的mp賦值為1;

模板

struct node

;//結構體

queuep;//佇列p

int mp[10005][10005];

int dx=;//方向陣列

int dy=;

// 計算從起點 start 到終點 ed 的最近距離

int bfs(node start, node target) );//將xx,yy,temp.step+1,當成結構體壓入佇列

mp[xx][yy]=1;//標記走過}}

}

這是乙個關於二維迷宮的題目。我們要從迷宮的起點 『s』 走到終點 『e』,每一步我們只能選擇上下左右四個方向中的乙個前進一格。 『w』 代表牆壁,是不能進入的位置,除了牆壁以外的地方都可以走。迷宮內的 『d』 代表一道上鎖的門,只有在持有鑰匙的時候才能進入。而 『k』 則代表了鑰匙,只要進入這一格,就會自動地拿到鑰匙。最後 『.』 則是代表空無一物的地方,歡迎自在的遊蕩。

本題的迷宮中,起點、終點、門跟鑰匙這四個特殊物件,每乙個恰好會出現一次。而且,此迷宮的四周 (最上面的一行、最下面的一行、最左邊的一列以及最右邊的一列) 都會是牆壁。

請問,從起點到終點,最少要走幾步呢?

輸入的第一行有兩個正整數h, w,分別代表迷宮的長跟寬。

接下來的h行代表迷宮,每行有乙個長度恰為w的字串,此字串只包含`'s'`, `'e'`, `'w'`, `'d '`, `'k'`, `'.'`這幾種字元。

請在一行中輸出乙個整數代表答案,如果無法從起點走到終點,請輸出-1。
示例1

4 12

wwwwwwwwwwww

we.w.s..w.kw

w..d..w....w

wwwwwwwwwwww

20
示例2

6 6

wwwwww

wews.w

w.wk.w

w.wd.w

w.w..w

wwwwww

-1
4 ≤ h, w≤ 500

's', 'e', 'k', 'd'各出現恰好一次

迷宮的四周(最上面的一行、最下面的一行、最左邊的一列以及最右邊的一列) 都會是 'w'

思路

從起點到終點一共存在兩種可行性

1)起點直接到達終點, 起點 -> 終點。

2)通過 起點s -> 鑰匙 -> 門-> 終點e。

最終到達終點的可行方案

1)如果不能直接從 起點s -> 終點e,需要考慮獲取鑰匙開門的途徑,如果仍然不能到達終點,則輸出 -1,否則輸出到達終點的最小步數。

2)如果起點s -> 終點e 可行,那麼獲取鑰匙開門到達終點必定可行,此時只需比較二者步數,獲得最小步數即可。

#includeusing namespace std;

int mp[505][505];//用來標記該點是否被走過

char migon[505][505];//輸入

int dx = ;

int dy = ;

int h,w;

struct car

st,ed,key,door;//定義起點,終點,鑰匙,門,四個結構體;

int bfs(car beg,car end)

} return -1;

} int main()

} memset(mp,0,sizeof(mp));

int ans1=bfs(st,ed);//直接從起點到終點,不開門

memset(mp,0,sizeof(mp));

int ans2=bfs(st,key);//從起點去拿鑰匙

memset(mp,0,sizeof(mp));

migon[door.x][door.y]='.';//拿到鑰匙將門變成點

int ans3=bfs(key,door);//拿了鑰匙去開門

memset(mp,0,sizeof(mp));

int ans4=bfs(door,ed);//開完門去終點

if(ans1==-1)//不拿鑰匙走不通的情況

;int dy=;

struct car

;queuep;

int bfs()

p.push();}}

}}int main()

);//將每個店當起點壓入佇列

} for(int i=1;i<=k;i++)

for(int i=1;i<=d;i++)

cout<

題目描述

有乙個n×

\times

×m的棋盤(1一行四個資料,棋盤的大小和馬的座標

輸出格式

乙個n×

\times

×m的矩陣,代表馬到達某個點最少要走幾步(左對齊,寬5格,不能到達則輸出-1)

輸入3 3 1 1

輸出

0    3    2    

3 -1 1

2 1 4

#includeusing namespace std;

int n,m,x,y;

int dx=;

int dy=;

int mp[1005][1005];

int a[1005][1005];//用來記錄起點到每乙個點的步數

struct car

;queuep;

void bfs(car st)

); a[xx][yy]=a[temp.x][temp.y]+1;

} }}

int main()

); for(int i=1;i<=n;i++)

cout<} return 0;

}

BFS例題 A計畫

c ontr ibcontrib a11y accessibility menu.js 關於 bfs要點 1 若為可化為的座標系圖形,可用結構體儲存其x值,y值和步數。一般開now 和 next now用於取出佇列裡面的結構體 next用於上下左右的運動計算,並且push到佇列中。2 在運用佇列時,...

BFS基礎例題

都是kuangbin的題 例1 poj2251 dungeon master 三維迷宮問題 題目大意 在三維空間中給出起點和終點,找最短的逃出去的路徑長 做法 bfs基礎上增加一維,本質是一樣的 const int maxn 2e6 7 const int inf 1e9 const ll inff...

bfs思路總結

1 將初始狀態加入佇列 2 初始狀態出隊,進行節點擴充套件。可能是狀態轉移,列出狀態轉移方程 3 在進行擴充套件中,需要判斷節點不要重複擴充套件。基本思路是設立visited陣列,標記狀態是否被訪問過。將狀態用乙個整數表示,整數則可以是陣列下標,該陣列下標對應的陣列元素的值即是狀態是否被訪問的標誌。...