1.对回溯算法的理解 回溯算法首先要确定问题的解空间,至少包含问题的一个(最优)解。之后从开始结点(根结点)出发,以深度优先方式搜索解空间。为了降低时间复杂度,需要建立限界函数或约束函数,进行剪枝。
2.“子集和”问题的解空间结构和约束函数
“子集和”问题的解空间结构可看做一颗完全二叉树,左子树为选择当前元素,右子树为不选择当前元素,第t层为第t个元素。
约束函数:
void Backtrack(int t) { if (sum == c) { flag = 1; return; } if (t > n) return; rest -= a[t]; if (sum + a[t] <= c) { b[t] = 1; sum += a[t]; Backtrack(t + 1); if (flag) return; sum -= a[t]; } if (sum + rest >= c) { b[t] = 0; Backtrack(t + 1); if (flag) return; } rest += a[t]; }
t为层数,sum为当前值的总和,c为目标值,flag为标志,标识是否找到问题的解,a[i]为第i个元素,b[i]为标记第i个元素是否已被使用,rest为除当前元素与已被使用元素之外的元素之和。当sum == c时,找到问题的解,当sum + a[t] <= c时,进入左子树,当sum + rest >= c时进入右子树(不满足条件则进行剪枝)。
3.在本章学习过程中遇到的问题及结对编程的情况
在本章结队编程中,我与队友在对函数的构建中出现了分歧,剪枝时函数的选择不同:回溯法的思想理解起来不难,但是用回溯法解题的方案也是有所区别,可有多种限界函数和约束函数的选择。但最终还是选择了队友更好的剪枝函数。