回溯算法
回溯法是一种组织搜索的一般技术,有“通用的解题法”之称,用它可以系统的搜索一个问题的所有解或任一解。
可以系统地搜索一个问题的所有解或任意解,既有系统性又有跳跃性。
回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。
这种以深度优先的方式系统地搜索问题的解的方法称为回溯法。
1 回溯算法的理论基础
1.1 问题的解空间
应用回溯法求解时,需要明确定义问题的解空间。问题的解空间应至少包含问题的一个(最优)解。
1.2 回溯法的基本思想
在生成解空间树时,定义以下几个相关概念:
活结点:如果已生成一个结点而它的所有儿子结点还没有全部生成,则这个结点叫做活结点。
扩展结点:当前正在生成其儿子结点的活结点叫扩展结点(正扩展的结点)。
死结点:不再进一步扩展或者其儿子结点已全部生成的结点就是死结点。
在确定了解空间的组织结构后,回溯从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。
在回溯法搜索解空间树时,通常采用两种策略(剪枝函数)避免无效搜索以提高回溯法的搜索效率:
- 用约束函数在扩展结点处减去不满足约束条件的子树;
- 用限界函数减去不能得到最优解的子树。
1.3 子集树与排列树
有时问题是要从一个集合的所有子集中搜索一个集合,作为问题的解。或者从一个集合的排列中搜索一个排列,作为问题的解。
回溯算法可以很方便地遍历一个集合的所有子集或者所有排列。
当问题是要计算n个元素的子集,以便达到某种优化目标时,可以把这个解空间组织成一棵子集树。
例如,n个物品的0-1背包问题相应的解空间树就是一棵子集树。
这类子集树通常有2n个叶结点,结点总数为2n +1-1。
遍历子集树的任何算法,其计算时间复杂度都是Ω(2n)。
当所给的问题是确定n个元素满足某种性质的排列时,可以把这个解空间组织成一棵排列树。
排列树通常有n!个叶子结点。因此遍历排列树时,其计算时间复杂度是Ω(n!) 。
例如,旅行商问题就是一棵排列树。
2 装载问题
给定n个集装箱要装上一艘载重量为c的轮船,其中集装箱i的重量为wi。集装箱装载问题要求确定在不超过轮船载重量的前提下,将尽可能多的集装箱装上轮船。
3 0-1背包问题
给定一个物品集合s={1,2,3,…,n},物品i的重量是wi,其价值是vi,背包的容量为W,即最大载重量不超过W。在限定的总重量W内,我们如何选择物品,才能使得物品的总价值最大。
4 图的m着色问题
给定无向连通图G=(V, E)和m种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中相邻的两个顶点有不同的颜色?
这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的两个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。
编程计算:给定图G=(V, E)和m种不同的颜色,找出所有不同的着色法和着色总数。
5 n皇后问题
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n皇后问题等价于在n×n格的棋盘上放置n个皇后,任何两个皇后不放在同一行或同一列或同一斜线上。
编程要求:找出一个n×n格的棋盘上放置n个皇后并使其不能互相攻击的所有方案。
6 旅行商问题
是指一销售商从n个城市中的某一城市出发,不重复地走完其余n—1个城市并回到原出发点,在所有可能的路径中求出路径长度最短的一条。本题假定该旅行商从第1个城市出发。
7 流水作业调度问题
给定n个作业的集合j={j1,j2,…,jn}。
每一个作业ji都有两道工序,分别在两台机器上完成。一台机器一次只能处理一道工序,并且工序一旦开始,就必须进行下去直到完成。
每一个作业必须先由机器1处理,然后由机器2处理。
作业ji需要机器j的处理时间为t[i][j],其中i= 1, 2, …, n ,j=1, 2。对于一个确定的作业调度,设F[i][j]是作业i在机器j上的完成处理的时间,所有作业在机器2上完成处理的时间之和定义如下:
称为该作业调度的完成时间之和。
由于只有两台机器,作业的处理顺序极大地影响结束时间f。流水作业调度问题要求对于给定的n个作业,制定最佳作业调度方案,使其完成时间和达到最小。
8 子集和问题
子集和问题的一个实例为<S,c>。其中,S={w1, w2, …, wn}是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得S1的和为c。
试设计一个解子集和问题的回溯法。
编程任务:对于给定的正整数集合S={w1, w2, …, wn}和正整数c,编程计算S的一个子集S1,使得S1的和为c。
9 ZOJ1145-Dreisam Equations
纸片上的符号只有数字,括号和等号。有足够的证据可以证明Dreisamwuste人只懂得三种运算符的运算:加,减和乘,而且算术运算没有优先规则:
他们只是严格地将每项数据从左边计算到右边。
例如,3+3×5,他们的计算结果是30,而不是18。
但现在纸片上的等式里没有任何算术运算符。
因此如果这些假设是正确的,而且这些数字能形成等式,那么这些运算符早已随时间而消逝了。