BFS入門筆記

才瓯發表於2024-12-08

BFS入門筆記

BFS廣度優先搜尋,在處理問題時,優先考慮更多的機會,而不是像DFS那樣優先走一條路,再回溯

BFS基於佇列實現,目的是把可能的解放在同一層處理,即BFS佇列中至多隻有兩層的解

考慮完前一層可能的解後,再考慮下一層的解。把當前解的後續解再放到佇列尾部。

img

如上圖中,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;
}

相關文章