我的程序的目的是通过递归递归地解决迷宫。但是,我的迷宫是一个N * N网格,每个方格都有一个方向属性:
NS,EW,NE,NW,SE,SW和X(阻塞方块)
每件都可以顺时针旋转90 *。
如果我正在为传统迷宫写一个递归解决方案,我会:
if (x,y outside maze) return false
if (x,y is goal) return true
if (x,y not open) return false
mark x,y as part of solution path
if (FIND-PATH(North of x,y) == true) return true
if (FIND-PATH(East of x,y) == true) return true
if (FIND-PATH(South of x,y) == true) return true
if (FIND-PATH(West of x,y) == true) return true
unmark x,y as part of solution path
return false
不幸的是,我正在与旋转部分挣扎。我的程序结构是一个填充方形对象的二维数组,它们保持当前的方向值和一个旋转函数。任何建议都将不胜感激。
答案 0 :(得分:0)
你的问题很混乱。你不可能通过一个单元格的指示和旋转它们的规则来表达你的意思。
话虽如此,所有递归回溯算法都采用了相似的形式:
solveFrom(current: State)
if current is complete
add current to solution set
else
for each possible step from state
solveFrom(state with step added)
state with step added
通常涉及添加步骤,递归调用函数然后再次删除它。
如果您只想要第一个解决方案(而不是所有可能的解决方案),那么该函数可以像您那样返回一个布尔值。
在您的情况下,我怀疑您的问题是可能的步骤包括移动到新单元格和旋转单元格。目前你只是尝试涉及移动的步骤。您需要尝试这些步骤的所有可能组合才能使算法正常工作。
答案 1 :(得分:0)
递归算法是深度优先的,效率很低,并产生任意解决方案(在您的情况下使用最大数量的北移动的路径)。
更合适的方法是广度优先,这将很容易产生最短的路径,并且减少无用的迭代。
话虽如此,增加旋转细胞的可能性意味着每个细胞具有潜在的4种状态(旋转0°,90°,180°和270°),尽管(NS,EW)组仅具有2种不同的状态。 由于某种原因,可能的单元格不包括4路交叉,实际上通过旋转不会改变,但在更一般的情况下可能发生。
因此,您需要记住(x,y,r)而不仅仅是(x,y),其中r是被访问单元格的旋转状态。
现在,当您选择下一个单元格时,您需要枚举所有可能的方向(对于NE,ES,SW,WN组为4,对于NS,EW组为2),然后检查每个单元是否存在路径,如果确实如此,只需使用(x,y)维护您的(x,y,r)路径信息。
至于广度优先算法,虽然它有点偏离主题,但基本上如下:
“候选人举动”是一个可能导致解决方案的举措。它包含一个单元格位置和方向,以及对前一个移动的引用(为了产生最终结果)
你还需要一个状态变量来跟踪已经尝试过的动作
它可以被视为一个布尔数组,即visited[x,y,r]
,但如果您不幸使用 primitive 这样的超高效语言,您可以使用关联内存或哈希表更有效地实现它。 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
该算法将检查从入口点并行产生的所有路径,直到它到达出口,遇到已经访问过的单元格(处于相同的旋转状态)或耗尽原始单元格进行检查(在这种情况下,牛头怪赢了)。
要重建解决方案,请按照退出移动前辈进行操作,直到第一次移动(没有父级)。