4

迷路ソルバープログラムを機能させましたが、出力される最終的なソリューションパスに、バックトラックされたスペース(壁にぶつかって向きを変えなければならなかった場所)が含まれているようです。次に例を示します。

ここに画像の説明を入力してください

以下の現在の実装でこれを防ぐにはどうすればよいですか?

int dir = 4;

bool visited[Max_Maze][Max_Maze][dir];


for (row = 0; row < size; ++ row)
{
  for (col = 0; col < size; ++ col)
  {
    for (dir = 0; dir < 4; ++ dir)
    {
      visited[row][col][dir]=false;
    }
  }
}

bool notSolved = true;
int path = 0;
row = 0;
col = 0;

rowStack.push(row);
colStack.push(col);

while (notSolved)
{

  //from perspective of person looking at maze on screen
  if (((row-1)>=0)&&(maze[row - 1][col] == 0)&&(visited[row][col][0]==false))
  {
    // if that space is not out of bounds and if you can go up
    // and you have not gone in that direction yet, go up
    visited[row][col][0] = true; 
    row--;
    rowStack.push(row);
    colStack.push(col);
    path++;
  }
  else if (((col+1)<size)&&(maze[row][col + 1] == 0)&&(visited[row][col][1]==false))
  {
    //else if you can go right etc., go right
    visited[row][col][1] = true;
    col++;
    rowStack.push(row);
    colStack.push(col);
    path++;
  }
  else if (((row+1)<size)&&(maze[row + 1][col] == 0)&&(visited[row][col][2]==false))
  {
    //else if you can go down etc., go down
    visited[row][col][2] = true;
    row++;
    rowStack.push(row);
    colStack.push(col);
    path++;
  }
  else if (((col-1)>=0)&&(maze[row][col - 1] == 0)&&(visited[row][col][3]==false))
  {
    //else if you can go left etc., go left
    visited[row][col][3] = true;
    col--;
    rowStack.push(row);
    colStack.push(col);
    path++;
  }
  else
  {
    //if stuck
    if (path == 0)
    {
      cout << "No Solution Path" << endl;
      notSolved = false;
    }
    else
    {
      rowStack.pop();
      colStack.pop();
      row = rowStack.top();
      col = colStack.top();
      path--;
    }
  }

  if((maze[row][col] == 0) && (row == (size - 1) && col == (size - 1)))
  {
    //if we reached an exit
    cout << "Solution Path:(in reverse)" << endl;
    for (int i = 0; i <= path; i++)
    {
      cout << "row:" << rowStack.top() << " col:" << colStack.top() << endl;
      rowStack.pop();
      colStack.pop();
    }
    notSolved = false;
  }
}

簡単な修正または完全なリストラが必要ですか?

4

2 に答える 2

3

ソルバーがその行き止まりに入ると、訪問した配列が3次元であるため、「(R、C)から直接訪問した」と記録されます。ただし、「 (R、C + 1)からにアクセスした」ことは記録されません。したがって、まったく同じ動きを2回行わない限り、同じ位置に2回移動しても問題ないと考えられます(右ではなくバックトラック時に左に移動するため、移動しません)。

訪問先を2次元配列に変更し、位置のみを記録し、移動は記録しない場合は、そのままで正常に機能するようです。次に、前に訪れたすべての正方形がそれ以上の動きをブロックしますが、正しい解決策でその正方形に戻る必要がある場合は、最終的にはそこに戻るのに十分なelseケースにヒットし、そこから3つは決してないはずです-探検するために広場を訪れた。

于 2011-11-30T20:20:22.300 に答える
0

特定の解決策についてコメントすることなく、やり直しを標準の深さ優先探索アルゴリズムと見なすことができます。これは、もう少し明確であることに同意すると思います。

boolean dfs (State s) {
    if (end_state(s)) {
        return true;
    }

    vector<option_t> options = generate_moves(s);
    for (vector<option_t>::iterator it = options.begin();
         it != options.end(); it++) {
        make_move(s, it);
        boolean found = dfs(s);
        if (found) {
            cout << s << endl;
        }
        undo_move(s, it);
        if (found) return true;
    }
    return false;
}

ご覧のとおり、これは次のものを作成できる限り機能します。

  1. 現在の迷路の状態を保持するいくつかのクラスの状態
  2. Stateがいつ解決されるかを知るend_state関数
  3. 現在の状態のすべてのオプションを見つけることができるgenerate_moves関数
  4. あなたの状態に対して移動を適用できるmake_move
  5. 状態に対する移動を元に戻すことができるundo_move
  6. 移動オプションを表すようにoption_tを定義します
  7. 状態の演算子<<を定義します

確かに、私が提供するソリューションには、バックトラックされたスペースの印刷に問題はありません(コードからも明らかなはずです)。

于 2011-11-30T20:21:04.037 に答える