从 DFS 到回溯法,再看 N 皇后问题
DFS 是深度搜索,是暴力的,是一条道走到黑的,是一次性搜到底的!那么,搜到底发现没有路了,就得回退去找另外的路,再继续莽着搜!既然要回退,就必须保存走过每个点的所有信息,包括先后顺序;这个回退的过程就叫 回溯。
根据回溯思想,演进到回溯算法来解决寻找问题。看一下 wiki 对回溯法的解释:
回溯法采用 试错 的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现,现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。
简化理解:回溯算法 = 树的深度优先搜索 + 剪枝函数
什么是剪枝函数?为了提高搜索效率,在搜索过程中使用约束函数,可以避免无谓地搜索那些已知不含答案状态的子树。如果是最优化问题,还可以使用限界函数剪去那些不可能含有最优解的子树。约束函数和限界函数目的相同,都是为了剪去不必要搜索的子树,减少问题求解所需实际生成的状态结点数,他们统称为剪枝函数。
OK,以上是概念介绍,下面来一道经典之经典之经典的回溯算法题:N皇后
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例 1:
示例 2:
<sub>N 皇后问题很多时候作为例题出现在教科书中,可以当做理解回溯算法的例题进行学习;</sub>
以 4 皇后问题为例,递归树如下:
解题思路:
回溯算法的通用解题思路就是在递归之前做选择,在退出递归之前撤销选择;
通过恰当的方式将不符合条件的情况剪枝;
回溯三部曲:
递归函数参数;
递归终止条件;
单层搜索的逻辑;
回溯模板:
JavaScript 实现:
代码作者:carlsun-2,已验证通过;
<hr>
回溯算法跟 DFS 深度搜索算法都很经典,需同步理解,对比、吸收;
我是掘进安东尼,公众号同名,日拱一卒、日掘一金,再会~
版权声明: 本文为 InfoQ 作者【掘金安东尼】的原创文章。
原文链接:【http://xie.infoq.cn/article/467e2ecb1ecc3f3bad00b66f2】。文章转载请联系作者。
评论