以 深度优先的方式系统地搜索问题的解的方法称为回溯法。
可以 系统地搜索一个问题的 所有解 或 任意解 。
有许多问题,当需要找出它的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。
回溯法的基本做法是搜索,或是一种组织得井井有条的,能 避免不必要搜索的穷举式搜索法 。
回溯算法解题思路
void backtrack(int i,int n,other parameters) //第i个位置,往往从0开始,n代表解空间的大小
{
if( i == n){
//get one answer
record answer;
return;
}
//求解空间第i个位置上的下一个解
for(next ans in position i of solution space)
{
backtrack(i+1,n,other parameters);
}
}
回溯法解题时通常包含3个步骤:
-
针对所给问题,定义问题的解空间;
-
确定易于搜索的解空间结构;
-
以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
回溯的问题的难度在于如何定义解空间
问题的解空间应至少包含问题的一个(最优)解。
解空间的特点:
(完全)二叉树.
问题的解是一棵子树(一条路)
通过深度优先搜索获得最优解
在生成解空间树时,定义以下几个相关概念:
活结点:
如果已生成一个结点而它的所有儿子结点还没有全部生成,则这个结点叫做活结点。
扩展结点:
当前正在生成其儿子结点的活结点叫扩展结点(正扩展的结点)。
死结点:
不能再进一步扩展或者其儿子结点已全部生成的结点就是死结点。
在回溯法搜索解空间树时,通常采用两种策略(剪枝函数)避免无效搜索以提高回溯法的搜索效率:
用约束函数在扩展结点处剪去不满足约束条件的子树;
用限界函数剪去不能得到最优解的子树。