递归算法是深度优先,效率低下并产生任意的解决方案(在您的案例中使用最大数量的北方运动的路径)。
一个更合适的方法是宽度优先,这将很容易产生最短路径,并且没有多少无用的迭代。尽管(NS,EW)组只有两种不同的状态,但增加旋转单元格的可能性意味着每个单元格可能具有4种状态(旋转0,90,180和270°)。 由于某些原因,可能的单元格不包含4路交叉,实际上这些交叉是通过旋转不变的,但是在更普遍的情况下可能发生。
因此,您需要记住(x,y,r)而不是(x,y),其中r是访问单元的旋转状态。
现在,当您选择下一个单元格时,您需要枚举其所有可能的方向(NE,ES,SW,WN组为4,NS,EW组为2),然后检查路径是否存在每一个,如果是这样,就像以前用(x,y)一样维护你的(x,y,r)路径信息。
至于广度优先算法,虽然它是有点偏离主题,它基本上是如下:
A“候选人的举动”是此举可能导致的解决方案。它包含一个单元格的位置和方向,加上前一个移动的引用(以便产生最终结果)。
你还需要一个状态变量来跟踪已经尝试过的动作。
它可以被看作是布尔值数组,即visited[x,y,r]
,虽然你可以更有效地与关联存储器或哈希表实现,如果你不幸使用原始超高效的语言,如C++ ...
你确定候选移动列表,并试戴顺序如下所示:
E = entry cell
candidates := singleton list containing (E.x, E.y, 0° rotation, no parent)
while candidates is not empty
C := get first element of candidates
if (C.x, C.Y) is the exit
// reconstruct solution path
path := empty list
do forever
path.add (C)
if C.parent == no parent
return path
C := C.parent
if C has not already been visited
mark C already visited
for each neighbour N of C // the 4 cells around (C.x, C.y)
for each rotation R of N // 0 for X, 2 for NS,EW, 4 for NE,ES,SW,WN
if there is a path from C to R
add (N.x, N.y, R, C) to candidates
return failure
该算法将检查并行地从入口点所产生的所有路径,直到它到达出口处,遇到一个已经访问过的细胞(在相同的旋转状态)或用完原始细胞来检查(在这种情况下,牛头怪赢了)。
要重建解决方案,请按照退出移动前辈直到第一次移动(没有父项)。
请给出一个这样的网格的例子,以及程序应该产生的解决方案。 – trincot
为什么有6个方向,而不是4或8?他们的意思是什么? –