在2D数组中遍历每个单元格

时间:2016-11-14 19:09:15

标签: arrays algorithm

我不确定该怎么称呼此问题,但我确定它有一个名字。否则找到答案会更简单。

给出"地图"细胞如:

O - - -
- X - -
- X X -
- - - -

其中O =起始位置,X =障碍物, - =未访问。我想遍历这张地图(我已经存储为2D数组)并访问尽可能多的单元格,而不会触及访问过的单元格。

我的算法如下:

  1. 如果我能走对,那就走吧。
  2. 如果我可以下楼,那就下去吧。
  3. 如果我可以向左走,请向左走。
  4. 如果我能上去,就上去吧。
  5. 如果我被卡住了,请回溯并标记该单元格"不可访问",然后返回1.
  6. 所以有两个问题:

    • 对于较大的地图,障碍物的数量和放置位置经常导致我的算法无法到达很多单元格。我已经尝试了不同的步骤1-4的顺序(即如果我可以等,总是会上升)但显然取决于给定的地图。
    • 我不知道什么时候停下来。如果我的算法到达"结束",即我实际上已经访问过每个可能的单元格,它就不会停止并且只是一直回溯到开始。

    所以我的问题是:有没有更好的方法来实现这个,或者我如何调整我当前的算法来解决这个问题?

2 个答案:

答案 0 :(得分:1)

有一个名称:最长路径问题:https://en.wikipedia.org/wiki/Longest_path_problem

以图表的形式,使从自由单元格到被阻挡单元格的边缘具有无限权重,并且所有其他边缘的权重均为1(或其他常数)。没有“有效”(在算法复杂性方面)解决这个问题(如果你找到一个你会出名!)

解决您的两个问题:

  1. 你是对的,根据障碍,你将无法访问某些方格,但它也取决于起点。很可能很多广场都无法到达;例如,完全围绕起点可能存在障碍物,然后所有障碍物都无法到达。

  2. 对于您当前的算法,您可以在回溯到起始方块后停止,然后再移动。否则您的算法看起来正确。步骤1-4的顺序最终不会有任何区别。为了知道哪条路径最长,你仍然需要全部尝试(使用这种方法)。

  3. 编辑:当我早些读到它时,我不确定我是否理解第5步;即使你被卡住了(如果你在那个广场然后你去过它),当前的广场也不应该被标记为无法到达,但周围的广场是(除了你来自的广场)。只要您不将当前方块标记为不可访问,回溯算法应该正确找到最长路径。

答案 1 :(得分:1)

由于以下情况,您的算法不起作用:

O - - -
X - - X

因为你的算法将首先完全正确

O 1 2 3
X - - X

并标记最后一个单元格在回溯时被阻止,因此它永远不会找到最佳

O 1 4 5
X 2 3 X

你可以通过将其视为一个图形问题并简单地应用任何最长路径算法(通常是NP-hard)来以通用方式解决这个问题但我不确定你是否熟悉这种方法

可能更简单的方法是:

  • 跟踪当前位置以及您到达目的地所采取的所有步骤。
  • 对于每个位置,您最终会尝试按顺序(R),向下(D),向左(L),向上(U)顺序踩到每个方向。
  • 当您尝试某个位置的所有方向时(例如,您尝试过U),请执行与您执行的最后一步相反的步骤。

一个例子可能有帮助。让我们再次考虑相同的例子。我使用C表示当前位置,使用#表示访问单元格。我们会跟踪移动的堆栈以及回溯的最后一步。

C - - -  Stack: []
X - - X  Backtracked move: -

向右走

# C - -  Stack: [R]
X - - X  Backtracked move: -

向右走

# # C -  Stack: [R, R]
X - - X  Backtracked move: -

向右走

# # # C  Stack: [R, R, R]
X - - X  Backtracked move: -

尝试向右,向下,向左和向上,注意你被卡住并回溯,即向右反转(左)

# # C -  Stack: [R, R]
X - - X  Backtracked move: R

最后一次回撤是正确的,所以现在尝试下一步,即下台

# # # -  Stack: [R, R, D]
X - C X  Backtracked move: -

尝试向右,尝试向下,向左走

# # # -  Stack: [R, R, D, L]
X C # X  Backtracked move: -

再次陷入困境,所以回溯

# # # -  Stack: [R, R, D]
X - C X  Backtracked move: L

最后一次退回的动作仍然存在,所以现在尝试下一步,即试试。请注意,我们陷入困境并进一步回溯。

快速转发到第一个有趣的下一步:

# C - -  Stack: [R]
X - - X  Backtracked move: R

最后一个是正确的,所以继续下去。

# # - -  Stack: [R, D]
X C - X  Backtracked move: -

你现在可能已经明白了,所以我只是一直快进:

# # # C  Stack: [R, D, R, U, R]
X # # X  Backtracked move: -

一路回溯:

C - - -  Stack: []
X - - X  Backtracked move: R

最后一步是正确的,所以请尝试向下,向左和向上。你已经完成了。

在此过程中,您将跟踪您所见过的最长路径,这就是您的答案。