对回溯法的理解:
回溯法本质就是深搜,对所有可能的结果进行搜索匹配,由于很多情况下结果很多,就需要进行适当的剪枝和分界限制来加快得到解。
回溯法用的最多的就是递归,其实也可用递推,但是递归比较符合人类逻辑
。
回溯法的解题通常是有模板的:
Void backtrack()
{
If(到达边界)
{输出答案/记录答案}
Else{ 记录这个点,现存结果更新,递归,现存结果还原,取消该点记录}
}
回溯法的有三种情况:
1):找所有可能解:通过一个结果数组记录搜索得到的解,然后再到达边界时输出
2):寻找其中过一个的解 : 同上;
2):寻找最优 (选和不选) 在边界点记录/更新最优值 + 在else中除了要对选取这个点的结果进行搜索还要对忽略这个点的结果进行搜索
回溯法的常用剪枝:
1) :判断该点在之后的所有点组合起来能不能到达最优或者超过当前最优。不能就剪枝
2)当前点是不是访问过,访问过忽略
2) 加上当前点是不是会越过限制条件,是的话剪枝
3) 如果只要求输出一个解,设立一个flag,有了一个答案之后设置flag为1,当flag为1时,全部return
子集和问题的解空间结构和约束函数:
假设给定集合 C = { x1,x2,x3 ……… xn}; 给定正整数P
解空间结构 C’ ={ xi,..xk} (1<=i<k<=n)
约束函数:
1:假设当前的搜索点为 Xi ((1<=i<n)),如果 {Xi+1 ,Xi+2,Xi+3………Xn}的和小于P,说明这个这个点取了也没用,剪枝;如果大于说明接下来的有可能得到P,那就继续搜索
2: 如果当前点大于P,该点不取
3: 如果当前点加上当前总和结果大于P,不取
本章学习遇到的问题:
主要是剪枝不充分,导致算法超时问题.
结对编程中问题:
主要是背包问题的剪枝,要按照严格限界,不然会超时。
这个限界也是之前没有用过限界函数.下面总结一下这个限界函数:
首先先要把数组进行降序排序,预测当前背包剩余容量最大可以装下多少价值的物品
如果剩余容量能够能够承载的最大价值 + 当前的背包价值 大于 当前的最优值,说明这个点可以继续搜索下去。小于,说明,如果装入这个物品,那么背包的剩余容量所能容纳的最大价都不能超过之前的最优值,说明该点不必取。
之所以先降序排序,是为了通过贪心算法判断上界,尽可能的取最大的。