C++ 从阵列为DFS解算器构建树
我正在使用DFS制作一个迷宫解算器,我想为它实现搜索树,但我对人工智能有点陌生,我想在这方面得到一些帮助 让我先举一个迷宫的例子:C++ 从阵列为DFS解算器构建树,c++,arrays,tree,depth-first-search,maze,C++,Arrays,Tree,Depth First Search,Maze,我正在使用DFS制作一个迷宫解算器,我想为它实现搜索树,但我对人工智能有点陌生,我想在这方面得到一些帮助 让我先举一个迷宫的例子: char maze[5][9] = "#########", "# # #", "# ## # #", "# # #", "#########", 因此,我的DFS搜索树应该如下所示: "#########", "#12#15 10 11 #", "#3##14 9 #12 #",
char maze[5][9] =
"#########",
"# # #",
"# ## # #",
"# # #",
"#########",
因此,我的DFS搜索树应该如下所示:
"#########",
"#12#15 10 11 #",
"#3##14 9 #12 #",
"#456 7 8 #13 #",
"#########",
父项的第一个子项->右单元格(如果为空)
父级的第二个子级->底部单元格(如果为空)
父项的第三个子项->左单元格(如果为空)
父项的第四个子项->顶部单元格(如果为空)
我的解算器将接收迷宫数组作为参数。我的问题是:
第一个问题:这就是我的参与者访问节点的方式吗
第二个问题:在代码中,我是否需要声明15岁是10岁的孩子?(在其他情况下,如9和14)
第三个问题:当我的解算器接收到数组时,我需要对数组进行预处理并从数组中构造树,还是我的参与者会在执行时构造树 我还假设“如果某个节点已经在解决方案树中,则不在该树中包含该节点”的规则?因为这确实有帮助
通常,树是隐式的,您只构建您实际访问的树的部分,通常在回滚时将其拆下
解算器跟踪树上的当前步骤。你可能还想跟踪你在迷宫中探索过的细胞。如果迷宫只有#
和
字符,请使用*
表示您已访问此解算器中的单元格
你从某个地方开始。如果该位置有效,则用*
标记它,这样就不会返回该位置,并将该位置(例如,(1,1)
)添加到路径的“堆栈”中
现在,你要遵守上面写的规则。检查当前位置下的单元格。是空的吗?(不是#
或*
)如果是,则递归,询问是否找到了出路
如果它找到了出路,则采用它找到的路径,在当前节点前面加上前缀,然后将该路径作为出路返回
如果没有,则在下一个相邻单元格中搜索(按上面的顺序)
最后,用调用它的函数包装上述递归例程,然后从映射中删除*
标记
您行走的树是隐式编码的。构建树会强制您访问每个节点,而您只想构建必须构建的部分
这可以通过多种方式进行优化。您可以通过处理地图的“幽灵”副本来避免写入地图。您可以通过将堆栈传递给递归版本来避免预结束,递归版本会在出现故障时小心地删除任何额外的节点,如果成功则保持打开状态。或者,您可以使用一个真正的堆栈,并使用一个包装函数向后编码路径,该函数(在所有工作完成后)将路径反转,使其以更常规的顺序排列。因此,如果我正确理解这一点,那么最终我的树将是包含最终路径的堆栈,并且仅此而已?如果我在墙上做了一个小动作(步骤2),然后我的递归例程让我离开那里回到前面的位置(在本例中是步骤1),我将步骤2标记为
'~'
,以避免无限循环(在每一步它都会检查它是否是'~'
),我还需要将该位置放在树中吗?现在我在第9步看到它,我不应该向左走而不是向上走吗?抱歉,如果我问的问题太多…@Powerbyte确实,您编写的路由与您应该递归的顺序不匹配。是的,唯一的状态是地图上的“划痕”和当前路线的“堆栈”。我假设目标是找到“这是可解的”和“给我一条路线,即使它很糟糕”?是的,目标是找到一条路线,任何路线,但我的主要问题是理解一棵树在内存中的表示方式,我认为带解决方案的堆栈将是解决方法。但理论上,DFS树显示每个访问的节点,因此我的堆栈甚至必须包含访问的节点“~”
,但这将留下一个不包含解决方案的堆栈,而是一个包含代理采取的整个路径的堆栈。所以我的主要问题是,我是否需要一个这样的堆栈,或者我应该把它全部废弃,只需要一个只包含解决方案的堆栈?最后,用书本的方式来表示它在内存中的正确方式是什么。(我想照本宣科,这样我就能最大限度地理解搜索算法在实际环境中如何看待事物,而不是理论环境)@powerbyte,这取决于你在做什么。DFS是一种通用技术。要使用pathfind,您不应该使用DFS,而应该使用类似于*。你的书或老师想要什么?问问他们。