步步为营(十六)搜索(二)BFS 广度优先搜索
上一篇講了DFS,那么與之相應的就是BFS。也就是 寬度優先遍歷,又稱廣度優先搜索算法。
首先,讓我們回顧一下什么是“深度”:
更學術點的說法,能夠看做“單位距離下,離起始狀態的長度”
那么廣度是什么呢?
個人認為,能夠這么歸納:
何為廣度? 能夠看做“距離初始狀態距離相等的結點”的集合
那么BFS的核心思想就是:從初始結點開始,搜索生成第一層結點。檢查目標結點是否在這些結點中,若沒有,再將全部第一層的結點逐一進行搜索,得到第二層結點,并逐一檢查第二層結點中是否包括目標結點。若沒有,再繼續搜索第二層全部結點……,如此依次擴展,直到發現目標結點為止。
這樣就保證了:假設我如今找到了目標結點(也能夠稱作當前問題的解)。那么我之前肯定沒有發現過目標結點,并且因為是廣度優先搜索。所以當前的解一定是距離起始結點近期的,也就是最優解。因為第一個解就是最優解,那么我們就能夠嘗試打印出道路。
偽代碼例如以下:
queue 結點隊列 queue.push(起始節點) while(結點隊列不為空) {queue.front();queue.pop();//取出頭結點if(頭結點是目標結點){跳出循環。}for(對下一層結點進行推斷) {if(結點滿足篩選條件){queue.push(滿足帥選條件的結點)}} }那么對于上一篇文章中果園的地圖,我們的部分狀態是這種:
S 0 1 1 0
0 1 0 0 0
0 0 1 1 0
0 1 0 0 0
0 0 0 0 G
從S點開始,設S點坐標為(1,1)
(1,1)
->(1,2)//第一層
->(2,1)//第一層
->(3,1)//第二層
->(3,2)//第三層
->(4,1)//第三層
……
->(5,5)//找到目標結點,結束
BFS因為維護了一個隊列。所以節省了遞歸須要消耗的時間,可是空間上卻比遞歸消耗的多的多。假設須要找多個解或者每一個節點的狀態比較多。可能會面臨空間超限的情況。
所以:
代表題目:HDU 1072 Nightmare
題目大意:在迷宮中有一個炸彈,過六個單位時間就會爆炸。要你求一個起點到迷宮的終點的最短距離,迷宮中有時間重置器,當你走到這個格子。炸彈的爆炸時間又一次置為0,迷宮中標識為墻壁的格子不能走。到達隨意一個格子時,炸彈計數器為0時,則失敗。
解題思路:最短距離。就想到用寬度優先遍歷,可是要一個輔助的數組來保存每一個格子的時間信息。因為每一個格子前進一步的花費時間單位是一樣的,所以寬度遍歷的結果自然是最短距離。因為時間單位有限制。僅僅能走六個單元,僅僅有在這六個時間單位里到達了終點,或者走到了時間設置開關把炸彈計時器置為0才干繼續走下去,所以要一個輔助數組來保存每一個格子剩余的最大時間單位,僅僅有走到當前的格子的剩余時間單位比之前的大時。這個狀態才干增加隊列中。
以下是代碼:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <algorithm>using namespace std;struct node {int x, y;int step;int t; };const int maxn = 9;int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; int maze[maxn][maxn], graph[maxn][maxn]; int n, m, ex, ey, ans;bool bfs(int x, int y);int main() {int test;scanf("%d", &test);while(test-- != 0){scanf("%d %d", &n, &m);int sx, sy;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){scanf("%d", &maze[i][j]);if(maze[i][j] == 2)sx = i, sy = j;if(maze[i][j] == 3)ex = i, ey = j;graph[i][j] = 0;}}if(bfs(sx, sy))printf("%d\n", ans);elseprintf("-1\n");}return 0; }bool bfs(int x, int y) {queue<node> que;node s;s.x = x;s.y = y;s.step = 0;s.t = 6;graph[x][y] = 6;que.push(s);while(!que.empty()){node st = que.front();que.pop();if(st.x == ex && st.y == ey){ans = st.step;return true;}if(st.t == 1)continue;for(int i = 0; i < 4; i++){int dx = st.x + dir[i][0];int dy = st.y + dir[i][1];if(dx >= 0 && dx < n && dy >= 0 && dy < m && maze[dx][dy] != 0){node tmp;tmp.x = dx; tmp.y = dy;tmp.step = st.step + 1;tmp.t = st.t - 1;if(maze[dx][dy] == 4)tmp.t = 6;if(tmp.t > graph[dx][dy]){graph[dx][dy] = tmp.t;que.push(tmp);}}}}return false; }總結
以上是生活随笔為你收集整理的步步为营(十六)搜索(二)BFS 广度优先搜索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Unity笔记】使用协程(Corout
- 下一篇: 分享:SringBuffer与Strin