BFS入門筆記
BFS廣度優先搜尋,在處理問題時,優先考慮更多的機會,而不是像DFS那樣優先走一條路,再回溯
BFS基於佇列實現,目的是把可能的解放在同一層處理,即BFS佇列中至多隻有兩層的解
考慮完前一層可能的解後,再考慮下一層的解。把當前解的後續解再放到佇列尾部。
如上圖中,BCDE
處在同一層考慮,那麼考慮到 B
的後續解時,把FGH
放在 CDE
後面,即CDEFGH
,基於佇列實現。
BFS每一層只往下走一步,當這一步的所有情況考慮完後,再考慮下一步的解
這裡以洛谷P1443為例:
透過BFS解決問題,首先要引入佇列這一資料結構
#include <queue>
處理座標,這裡使用構造結構體的方法,得到橫縱座標
struct pos {
int x, y;
};
定義佇列,儲存我們當前考慮的點(座標位置)
queue<pos> p;
儲存地圖,一般分為已訪問路徑的圖和存路徑的圖
int map[405][405], ans[405][405];
向量變數,本題中,馬可走 “日” 字,則向量如下
int dx[] = { 1,2,2,1,-1,-2,-2,-1 };
int dy[] = { 2,1,-1,-2,-2,-1,1,2 };
BFS函式的寫法:
void bfs(int sx, int sy) {
memset(ans, -1, sizeof(ans));
p.push({ sx,sy });
ans[sx][sy] = 0;
map[sx][sy] = 1;
while (!p.empty()) {
pos t = p.front();
p.pop();
for (int i = 0; i < 8; i++) {
int tx = t.x + dx[i], ty = t.y + dy[i];
if (check(tx, ty)) {
p.push({ tx,ty });
map[tx][ty] = 1;
ans[tx][ty] = ans[t.x][t.y] + 1;
}
}
}
}
其中,我們先使 ans
陣列的值全部初始化為 -1
即一開始所有的點走還沒考慮(都走不到)。
將出發點 sx,sy
放進佇列,從這個點開始考慮存在的解。
賦值 ans[sx][sy],map[sx][sy]
,初始時,出發點能夠走到(走 \(0\) 步),且已經被走過。
當佇列不空時,使用向量變數,計算下一步的位置。
check
函式檢查下一步的位置是否合法
int check(int x, int y) {
if (x<1 || x>n || y<1 || y>m) return 0;//越界非法
if (map[x][y]) return 0;//走到已走過的位置上非法
return 1;
}
判斷合法後,標記這個位置已經走到過 map[tx][ty] = 1
,且走到這個位置的步數為走到上一個點的步數加 \(1\) 步,ans[tx][ty] = ans[t.x][t.y] + 1
。
最後根據題意,輸出我們的所有路徑的地圖即可
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
printf("%d ", ans[i][j]);
}
printf("\n");
}
完整程式碼:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <queue>
#include <cstring>
#include <stdlib.h>
using namespace std;
struct pos {
int x, y;
};
int n, m, sx, sy;
queue<pos> p;
int map[405][405], ans[405][405];
int dx[] = { 1,2,2,1,-1,-2,-2,-1 };
int dy[] = { 2,1,-1,-2,-2,-1,1,2 };
int check(int x, int y) {
if (x<1 || x>n || y<1 || y>m) return 0;
if (map[x][y]) return 0;
return 1;
}
void bfs(int sx, int sy) {
memset(ans, -1, sizeof(ans));
p.push({ sx,sy });
ans[sx][sy] = 0;
map[sx][sy] = 1;
while (!p.empty()) {
pos t = p.front();
p.pop();
for (int i = 0; i < 8; i++) {
int tx = t.x + dx[i], ty = t.y + dy[i];
if (check(tx, ty)) {
p.push({ tx,ty });
map[tx][ty] = 1;
ans[tx][ty] = ans[t.x][t.y] + 1;
}
}
}
}
int main()
{
scanf("%d %d %d %d", &n, &m, &sx, &sy);
bfs(sx, sy);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
printf("%d ", ans[i][j]);
}
printf("\n");
}
return 0;
}