在学习数据结构算法的时候,常常会被N多个算法思想绕昏头脑,比如有蛮力法、分治法、动态规划法、贪心法、回溯法、分支界定法等等。我常常易混淆的就是回溯法和分支界定法。
两者都是建立解空间树,然后按照一定的约束条件进行遍历,找到解。
1、回溯法:是按照深度优先搜寻建立解空间树
分支界定法:是按照广度优先搜寻建立解空间树
2、回溯法:是蛮力法的改进,蛮力法构造全部解,而回溯法每次只构造可能解的一部分, 然后评估这个部分解, 如果这个部分解有可能导致一个完整解, 则对其进一步构造, 否则, 就不必继续构造这个部分解了。
分支界定法:在遍历过程中, 对已经处理的每一个结点根据限界函数估算目标函数的可能取值, 从中选取使目标函数取得极值( 极大或极小)的结点优先进行广度优先搜索, 从而不断调整搜索方向, 尽快找到问题的解。
例如, 对于n= 3 的0/ 1 背包问题, 3 个物品的重量为{20 , 15 , 10} , 价值为{20 , 30 ,25} , 背包容量为25 , 从解空间树的根结点开始搜索, 回溯法搜索过程如下:
(1 ) 从结点1 选择左子树到达结点2 , 由于选取了物品1 , 故在结点2 处背包剩余容量是5 ,
获得的价值为20;
(2 ) 从结点2 选择左子树到达结点3 , 由于结点3 需要背包容量为15 , 而现在背包仅有容量5 , 因此结点3 导致不可行解,
对以结点3 为根的子树实行剪枝;
(3 ) 从结点3 回溯到结点2 , 从结点2 选择右子树到达结点6 , 结点6 不需要背包容量, 获得的价值仍为20
;
(4 ) 从结点6 选择左子树到达结点7 , 由于结点7 需要背包容量为10 , 而现在背包仅有容量5 , 因此结点7 导致不可行解, 对以结点7
为根的子树实行剪枝;
(5 ) 从结点7 回溯到结点6 , 在结点6 选择右子树到达叶子结点8 , 而结点8 不需要容量, 构成问题的一个可行解( 1 ,
0 , 0) , 背包获得价值20。
按此方式继续搜索, 即可得到搜索空间树如下图所示:
分支界定法法搜索过程, 具体的搜索过程如下图所示:
假设界定函数为:界定目标值=现有价值+背包剩余容量*剩余物品的最大单位重量价值
(1 ) 在根结点1 , 没有将任何物品装入背包, 因此, 背包的重量和获得的价值均为0
,根据限界函数计算结点1 的目标函数值为0+(25-0)*2.5。
(2 ) 在结点2 , 将物品1 装入背包, 因此背包的重量为10 ,
获得的价值为25 , 目标函数值为25 + ( 25 - 10)×2 , 将结点2 加入待处理结点表 中; 在结点3 , 没有将物品1装入背包, 因此背包的重量和获得的价值仍为0 , 目标函数值为0+(25-0)*2, 将结点3 加入待处理结点表 中。
(3 ) 在待处理结点表 中选取目标函数值取得极大的结点2
优先进行搜索。
(4 ) 在结点4 , 将物品2 装入背包, 因此背包的重量为25 , 价值为55,目标函数值为55 + ( 25 - 25)×1,
将结点4加入待处理结点表 中;在结点5 , 没有将物品2 装入背包, 因此背包的重量和获得的价值与结点2 相同,目标函数值为25 + ( 25-10) ×1
= 40 , 将结点5 加入待处理结点表 中。
(5 ) 在待处理结点表中选取目标函数值取得极大的结点4 优先进行搜索。
(6 ) 在结点6 , 将物品3
装入背包, 因此, 背包的重量为45 , 不满足约束条件, 将结点6丢弃; 在结点7 , 没有将物品3 装入背包,因此背包的重量和获得的价值与结点4 相同,
目标函数值为55 + (25-25) ×0= 55。
(7) 由于结点7 是叶子结点, 同时结点7的目标函数值是待处理结点表 中的极大值, 所以结点7 对应的解即是问题的最优解, 搜索结束。