[解決済み] BFS迷路ヘルプ c++
質問
ブレッドファースト探索を用いた迷路解法を作成し、最短経路を文字'*'でマークしようとしています。
迷路は、実はただのテキストの束です。迷路はn×nのグリッドで構成され、壁を表す"#"と、歩けるエリア/パスを表すピリオド"."で構成されています。S'はスタート、'F'はフィニッシュを表します。 今現在、この関数は解を見つけることができないようです(解がありえないのに解があると思い込んでいます)。 私は4つの隣人をチェックし、それらが「未発見」(-1)であれば、処理するためにキューに追加されます。
いくつかの迷路ではうまくいくのですが、この迷路ではうまくいきません。
...###.#....
##.#...####.
...#.#.#....
#.####.####.
#F..#..#.##.
###.#....#S.
#.#.####.##.
....#.#...#.
.####.#.#.#.
........#...
私のロジックに足りないものは何だろう?
int mazeSolver(char *maze, int rows, int cols)
{
int start = 0;
int finish = 0;
for (int i=0;i<rows*cols;i++) {
if (maze[i] == 'S') { start=i; }
if (maze[i] == 'F') { finish=i; }
}
if (finish==0 || start==0) { return -1; }
char* bfsq;
bfsq = new char[rows*cols]; //initialize queue array
int head = 0;
int tail = 0;
bool solved = false;
char* prd;
prd = new char[rows*cols]; //initialize predecessor array
for (int i=0;i<rows*cols;i++) {
prd[i] = -1;
}
prd[start] = -2; //set the start location
bfsq[tail] = start;
tail++;
int delta[] = {-cols,-1,cols,+1}; // North, West, South, East neighbors
while(tail>head) {
int front = bfsq[head];
head++;
for (int i=0; i<4; i++) {
int neighbor = front+delta[i];
if (neighbor/cols < 0 || neighbor/cols >= rows || neighbor%cols < 0 || neighbor%cols >= cols) {
continue;
}
if (prd[neighbor] == -1 && maze[neighbor]!='#') {
prd[neighbor] = front;
bfsq[tail] = neighbor;
tail++;
if (maze[neighbor] == 'F') { solved = true; }
}
}
}
if (solved == true) {
int previous = finish;
while (previous != start) {
maze[previous] = '*';
previous = prd[previous];
}
maze[finish] = 'F';
return 1;
}
else { return 0; }
delete [] prd;
delete [] bfsq;
}
解決方法は?
近傍のイテレーションを大幅に簡略化することができます(これはkobraが提案するものと多少似ていますが、さらに改善することができます)。私は、与えられた手の x と y のデルタを定義する moves 配列をこのように使用します。
int moves[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
これは、与えられたセルから可能なすべての手をリストアップするだけでなく、いくつかの問題で有用な時計回りの方向にもリストアップすることに注意してください。
さて、この配列をたどるには
std::queue<pair<int,int> >
このように、現在の位置はそれに対応する座標の組で定義される。以下は、あるセル c の近傍を循環させる方法である。
pair<int,int> c;
for (int l = 0;l < 4/*size of moves*/;++l){
int ti = c.first + moves[l][0];
int tj = c.second + moves[l][1];
if (ti < 0 || ti >= n || tj < 0 || tj >= m) {
// This move goes out of the field
continue;
}
// Do something.
}
このコードはあなたのコードとはあまり関係ありませんが、私はこの種の問題を教えているので、このアプローチを見せたとき、多くの学生が本当に感謝してくれたことを信じています。
終点の位置から始めて、prd配列を使ってその親を見つけ、さらにその親の親を見つけ、というように、負の親を持つセルに到達するまで続ける必要があります。その代わり、訪問したすべてのセルを考慮し、そのうちのいくつかは
S
から
F
.
を設定すると、一度ブレークすることができます。
solved = true
を使用すると、アルゴリズムが少し最適化されます。
個人的には、場外転落のチェックがないので、必ず解が見つかると思います。(その
if (ti < 0 || ti >= n || tj < 0 || tj >= m)
のビットがあります)。
これが、あなたのコーディングの改善のヒントになれば幸いです。
関連
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】致命的なエラー LNK1169: ゲームプログラミングで1つ以上の多重定義されたシンボルが発見された
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】画像を使った迷路の表現と解き方
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] テスト
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません