我真正的问题是,'为什么不回溯加速我的搜索?'但是我不确定如果没有更多的背景,这是否有意义......
这个问题实际上只是学术性的 - 代码“有效”,我的程序找到了我期待的解决方案....但我想确保我理解术语。为了帮助说明事情,让我们使用一个特定的例子,我们需要一个搜索算法 - n-Queens问题。
n-queens problem - 将n个皇后放置在n×n棋盘上,使得没有女王可以攻击另一个棋盘。
一个解决方案
在互联网上有很多的示例代码,可以找到搜索“N-queens backtracking”,维基百科关于回溯的文章甚至使用N-Queens解释回溯是什么(http://en.wikipedia.org/wiki/Backtracking)。根据我的理解,这个想法是,如果一个无效的电路板配置 - 让我们说两个可以相互攻击的地方,这个算法忽略了通过添加额外部分而产生的所有电路板配置。
我还实现了一个(非递归/非回溯)Depth-first和广度优先版本的搜索。正如预期的那样,两种变化都会测试完全相同的状态数。我期望一个递归的,深度优先的回溯算法应该测试更少的状态。但我没有看到。
Depth First
Found 92 solutions in 10.04 seconds
Tested 118969 nodes (1.2k nodes per second)
Largest Memory Set was 64 nodes
BackTracking
Found 92 solutions in 9.89 seconds
Tested 118969 nodes (1.2k nodes per second)
Largest Memory Set was 170 nodes
Breadth First
Found 92 solutions in 12.52 seconds
Tested 118969 nodes (0.95k nodes per second)
Largest Memory Set was 49415 nodes
我的实际实现是通用的,所以我没有利用板镜/旋转或其他任何聪明的东西。
我觉得我一定是误会,但我不知道回溯带给我的好处是什么?
维基百科解释说,一旦某个状态被发现无效,它的子树就会被跳过(修剪),但是合理地放置皇后(避免a8中的Q1和Q1中的Q1)似乎可以防止任何可以修剪的情况?
我的呼吸优先实现应该考虑回溯避免哪些电路板配置?
答案 0 :(得分:4)
回溯是避免搜索错误路径的几种方法之一。启发式,就像“合理地”放置女王一样。您的非回溯解决方案必须具有足够好的启发式,以避免搜索所有无效路径。根本没有修剪的解决方案将测试板上每个(64选8)排列的皇后。
答案 1 :(得分:1)
Vanilla回溯与深度优先搜索相同。你的分支越来越深,当你无法继续前进时(因为没有更多的皇后可以放在棋盘上)你会向后追踪你的路径,然后尝试树的另一个分支 - 因此“回溯”。
您的深度优先搜索和“回溯搜索”可能是相同的算法,仅具有整体差异。当你在棋盘上有6个皇后且没有更多的皇后适合那里时,你无法“理性地”继续进行搜索,所以你的深度优先搜索可能会在那里停止(而不是枚举通过添加第7个所得到的所有无效配置)和董事会任何地方的第8位女王。)
答案 2 :(得分:0)
维基百科对回溯的描述混淆了(i)重新访问节点以考虑未访问的分支和(ii)修剪节点,例如通过强制执行local consistency的算法。如果不执行(ii),则访问节点计数不会减少。