【问题标题】:Maze solver recording backtracked paths迷宫求解器记录回溯路径
【发布时间】:2011-11-30 19:56:55
【问题描述】:

我已经让我的迷宫求解器程序开始工作,但它似乎在它输出的最终解决方案路径中包含了回溯空间(它到达并撞到墙壁的地方,因此它不得不转身)。这是一个例子:

如何在下面的当前实现中防止这种情况:

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;
  }
}

需要简单的修复还是整体重组?

【问题讨论】:

  • 它只是打印找到的第一个解决方案还是所有解决方案?
  • 是的,它没有找到最快的或任何东西,只是第一个

标签: c++ maze


【解决方案1】:

当求解器直接进入死胡同时,它会记录它已经“从 (R, C) 访问”,因为您访问的数组是三维的。但它从未记录它“从 (R, C + 1) 访问left”。所以它认为两次移动到相同的 position 是可以的,只要它不进行两次完全相同的移动(它没有,因为它在回溯时向左移动,而不是向右移动)。

如果您将visited 更改为二维数组并且只记录位置,而不是移动,它看起来会正常工作。然后你之前访问过的每一个方格都会阻止进一步的移动,但这没关系,因为如果正确的解决方案需要回到那个方格,你最终会遇到足够的 else 情况来弹回它,并且从那里三个必须是永不-参观广场探索。

【讨论】:

  • 好的,我想我正确地实现了这个更改:pastebin.com/67pdjtxT 仍然有同样的问题:imgur.com/3h9GZ 这一次它只包含一个回溯空间?
  • @mwmnj 我没有时间详细阅读您的代码(这是您的作业,不是我的),但我能想到许多可能出错的地方。确保将起始广场记录为已访问。如果您在离开之前记录了一个访问过的广场,请确保您也在 pop 案例中执行此操作。如果您在进入之前记录了访问过的广场,请确保您记录的是您将要去的广场,而不是您当前所在的广场。如果这些都没有错,请逐步执行您的代码找出它应该弹出时回溯的位置,并找出原因。
  • 忘记标记第一个访问的广场,感谢您的帮助!
【解决方案2】:

在不评论您的具体解决方案的情况下,您可能会考虑将重做作为标准的深度优先搜索算法,我认为您会同意它更清楚一些:

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. end_state 函数知道 State 何时处于解决方案中
  3. generate_moves 函数可以找到当前状态的所有选项
  4. make_move 可以针对您的状态应用移动
  5. undo_move 可以撤消针对状态的移动
  6. 您定义 option_t 使其代表移动选项
  7. 定义运算符

我可以告诉你,我给你的解决方案肯定没有打印回溯空格的问题(也应该从代码中清楚)。

【讨论】:

    猜你喜欢
    • 2012-01-09
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 2014-05-08
    • 2015-05-17
    • 1970-01-01
    相关资源
    最近更新 更多