幅優先探索(BFS)を学ぶ

同期が幅優先探索の勉強会を開いてくれたので、覚えられるように書いときます。

幅優先探索とは、グラフ探索の一解法だそうです
他にも深さ優先探索(DFS)があるそうです

以下参考文献
https://qiita.com/drken/items/996d80bcae64649a6580


んで、今回実装した例
理解のためにいろいろコメントを入れてます

# 今回、dequeというモジュールを使用、キューだけでなくスタックチックな用途にも使える
from collections import deque

# 入力をすべて受ける
r, c = map(int, input().split())
sy, sx = map(int, input().split()) # START
gy, gx = map(int, input().split()) # GORL

# マス目と数と合わせるためにすべて引く、
sy -= 1
sx -= 1
gy -= 1
gx -= 1

# 今回この書き方で値取得できるの知れたのがよかった
grid = [input() for _ in range(r)]

# print(grid)
# dequeの宣言は以下、初期値を入れる
q = deque()
q.append((sy, sx))

# 距離の情報を保持するdistを作成、スタート地点には0を入れる
INF = -1 #1<<60 # 2: 0001 1<<3: 1000
dist = [[INF for _ in range(c)] for __ in range(r)]
dist[sy][sx] = 0

# 下に行くとY、正 右にいくとX、正
# ↓→↑←を文字列に置き換えた
dy = (0, 1, 0, -1)
dx = (1, 0, -1, 0)

# キューがなくなるまで続ける
while(len(q) > 0):

    # 左側から取り出してnowに入れる、現在の座標がy, xに入る
    now = q.popleft()
    y, x = now

    # ↓→↑←それぞれに対して、一つずつ動かした後の座標を入れる
    for di in range(4):
        ny = y + dy[di]
        nx = x + dx[di]
        
        # 更新後の座標が枠をはみ出る、0より小さくなったら何もしない
        if (ny<0 or ny>=r or nx<0 or nx>=c): continue
        # 更新後の座標に#があったら何もしない
        if (grid[ny][nx] == '#'): continue
        # 更新後の座標に何かしら値が入ってたら何もしない(更新しない)
        if (dist[ny][nx] != INF): continue
        
        # 距離の更新、現在の距離に+1をする
        dist[ny][nx] = dist[y][x] + 1
        # 更新後の座標を新たにキューに入れる
        q.append((ny, nx))

# これは、whileループをこなすごとにキューにどんどん値が入ってくるが、
# それらには値が一度でも入れば更新されず、やがてはすべての範囲を調べつくすので
# 値が入りきったら終わり、ということか

# for i in range(r):
#     for j in range(c): print(dist[i][j], end='')
#     print()

print(dist[gy][gx])

なるほど、、、奥が深いなぁ
これを自分で実装するのはなかなかにハードルが高いが、
類似問題を色々やってみようと思う

以上