【问题标题】:Improving maze search改进迷宫搜索
【发布时间】:2013-04-19 10:15:26
【问题描述】:

我做了一个简单的迷宫搜索算法,盲目地跑到一个单元格的每个方向 检查是否找到了目标。它可以找到目标,但解决方案仍然很糟糕,因为它不会在找到目标时终止其他递归调用 它绘制了它已经走过的所有路径,而不仅仅是一条通往目标的可能路径。我该如何改进呢?

伪代码中的基本算法是这样的:

function searchMaze(start_point, end_point, maze) {

 // If current point is goal I would like to abort other recursive calls
 if(start_point.equals(end_point)) {
   pathFound = true;
   drawPathInArray(); 
    return;
  }
 else {
    // if current point is not inside the array
   if(start_point_not_within_array)
   return
   else {
     // if current point is a wall or a cell that has already been visited
     if(cell_is_wall || cell_is_visited)
       return;
      else {
           // mark cell as possible path
           markCellInPathArray("#");
           setCellVisited();
           searchMaze(left_from_start_point, end_point, maze);
           searchMaze(right_from_start_point, end_point, maze);
           searchMaze(above_start_point, end_point, maze);
           searchMaze(below_start_point, end_point, maze); 
      }
   }
  }
}

【问题讨论】:

  • 您为我们提供的算法限制不足。请通过添加进行编辑:1)您希望如何重现 2)终止条件
  • 尝试使用 BFS - 广度优先搜索。它可以在不使用递归的情况下实现。

标签: java recursion backtracking maze


【解决方案1】:

让函数返回一个布尔值。每当您找到通往目标的路径时,返回 true,否则返回 false。从其中一个递归调用中获得返回值为 true 后返回。

所涉及的更改将是适当的返回语句并将您的 4 个递归调用更改为:

if (searchMaze(left_from_start_point, end_point, maze))
  return true;
if (searchMaze(right_from_start_point, end_point, maze))
  return true;
if (searchMaze(above_start_point, end_point, maze))
  return true;
if (searchMaze(below_start_point, end_point, maze))
  return true;

另外,你不应该在最后有一个setCellNotVisited() 吗?

注意:我看到你已经有一个pathFound 变量(可能是一个类变量)。在这种情况下,可能首选 Marco 的解决方案,但最好将其更改为返回值。

【讨论】:

  • 谢谢,那是我忘记了。剩下的就是消除不必要的死胡同。我问自己,使用字符串数组来存储迷宫单元是否是个好主意,或者创建一个存储字符串、“已访问”属性并了解其周围单元的单元类是否会更好。
  • @user1812379 我可能会使用byte[][] 来表示值,boolean[][] 来表示已访问。不过,只要在正确的位置将visited 设置为false,就可以将visited 合并到值数组中(只需将其设为墙或给它一个单独的值)。我个人不喜欢 String[] 来表示矩阵 - 太不可变且不直观。
  • 谢谢,但字符串仅用于打印迷宫符号。我不想使用数字。对于访问的标志,我使用布尔数组。第二句我还没看懂。
  • @user1812379 第二句还是第三句? 第二次 - 可视化 - 当你访问一个单元时,建造一堵墙,当你回溯时,将其移除。 3rd - Strings 是不可变的 - 你无法更改它们。因此,“将 x 行、y 列的单元格设置为某个值”将涉及获取 String 行,将其更改为 char[],修改正确的值,将其转换回 String 并将其分配回数组.对于byte[][],它只是maze[x][y] = newValue。这是不直观的,因为每一行(或列)都是一个String(实际上只是一个数组,但无论如何)而不是一个数组,这更有意义。
  • 第二句。 “消除不必要的路径”背后的想法并不明确。
【解决方案2】:

你应该在每个递归调用中添加你的标志:

pathFound = pathFound || searchMaze(left_from_start_point, end_point, maze);
pathFound = pathFound || searchMaze(right_from_start_point, end_point, maze);
pathFound = pathFound || searchMaze(above_start_point, end_point, maze);
pathFound = pathFound || searchMaze(below_start_point, end_point, maze);

如果 pathFound 为真,则忽略调用。

【讨论】:

    【解决方案3】:

    在 else 块中,如果你设置为 true

    1) cell_is_wall when wall is visited 
    2) set start_point_not_within_arrary when it is not in the array
    

    那么你的代码应该可以工作了。您已经拥有的这些条件检查将处理其他递归调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-22
      • 1970-01-01
      • 2014-12-11
      • 2020-06-14
      相关资源
      最近更新 更多