幅優先探索による迷路の探索
幅優先探索で迷路の最短ルート探索をしました。
色々ネットで調べて見たのですが、意外とピンとくるものがなかったため、備忘録として...。
例題としてはAtCoderの幅優先探索の問題を使っています。
C - 幅優先探索
#ただし本質ではないステップ数をどうやって数えるかで、少し苦労しました。
#include <iostream> #include <string> #include <queue> using namespace std; //サイズが大きいため、Globalで宣言する。 //関数間での受け渡しも不要になる。 //step数の保存はsrcリストに格納する。 int R, C; int sx, sy, gx, gy; char c[55][55]; bool visited[55][55]; int src[55][55]; int dx[4] = {1, 0, -1, 0}; int dy[4] = {0, 1, 0, -1}; queue<int> xq; queue<int> yq; void init(){ /** *標準入力からの値の読み込み *Global変数の初期化 */ cin >> R >> C; cin >> sx >> sy; sx -= 1; sy -= 1; cin >> gx >> gy; gx -= 1; gy -= 1; for(int i = 0; i < R; ++i){ for(int j = 0; j < C; ++j){ cin >> c[i][j]; visited[i][j] = false; } } visited[0][0] = true; src[sx][sy] = 0; } int main(){ //次のステップの位置 int xNext, yNext; //値の読み込みと変数の初期化 init(); //スタート位置をqueueにpushする。 //queueはxとyを別々に作る。 xq.push(sx); yq.push(sy); //BFSのループ do{ int xi = xq.front(); int yi = yq.front(); xq.pop(); yq.pop(); //dx,dyを使って上下左右を探索する。 //'.'であればqueueに格納する。 for(int i = 0; i < 4; ++i){ xNext = xi + dx[i]; yNext = yi + dy[i]; if(c[xNext][yNext] == '.' && !visited[xNext][yNext]){ xq.push(xNext); yq.push(yNext); visited[xNext][yNext] = true; src[xNext][yNext] = src[xi][yi] + 1; //Goal時の処理 if(xNext == gx && yNext == gy){ cout << src[xNext][yNext] << endl; return 0; } } } //x,yのqueueが共に空であれば終了する。 }while(!xq.empty() || !yq.empty()); return 0; }
グラフのような1次元探索だとQueueが一つで済んで分かりやすいのですが、
2次元の迷路のようなものだとQueueが二つ必要なので直感的には少し分かりにくいなぁという感じ...。