0/1背包问题
本篇是用回溯法求解0/1背包问题,结合上篇回溯法求解的步骤(忘了的小伙伴可以再看下),我们来对这个问题进行分析,
解决思路:
(1)确定问题的解题空间树:从n个集合中求取最优解,很显然其解空间是子集树(每个物品要么装入,要么不装入)。每个结点表示背包的一种选择状态。
(2)确定结点的扩展规则:对于本问题的解空间树,用i表示层数,第i层上的某分枝结点的对应状态dfs(i,tw,tv,rw,op),tw当前背包中物品重量,tv当前背包中物品价值,rw(剪枝函数时用到)考虑第i个物品时剩余物品的重量,op解向量。拓展可能有两种:
(1)选择第i个物品放入背包,tw=tw+w[i],tv=tv+v[i],(这里先不讲rw的用法,可以先不管),op[i]=1,接着转向下一个状态dfs(i+1,tw,tv,rw,op),这是左分枝。
(2)不选择第i个物品,op[i]=0,tw=tw,tv=tv,转向下一个状态dfs(i+1,tw,tv,rw,op),这是右分枝。
例:对于层次为1的根结点为(0,0),考虑物品1(这里的数据我下面会给出,这里大家就当成参考数据来看)
(1)选择物品1:op[1]=1,tw=0+5=5,tv=0+4=4,产生新的结点(5,4)作为根的左孩子。
(2)不选择物品1:op[1]=0,tw=0,tv=0,产生新的结点(0,0),作为根的右孩子。
w[]数组是存放物品的重量,v[]数组是存放物品的价值,W背包容量
(3)以深度优先方式搜索解空间树,并采用剪枝函数避免无效搜索,提高效率:对于左枝点(物品都放包内)可能会出现tw+w[i]>W的情况,所以这些完全可以删去,所以满足tw+w[i]<=W,的结点才可以继续往纵深走。对于右枝点(物品不放包内),我们添加一个参数rw(考虑i物品时