0/1背包问题-回溯法

前提条件:物体按价值重量比非递增排序

 

回溯法(循环迭代回溯)

 

 

方案一:

 

1.将物体装入背包(搜索此物体的左分支),直到第i个物体不能装入时(此时进入第i个物体的右分支搜索),试探下一个物体;

 

2.当试探完第n个物体时(即已到达空间树的叶子结点,搜索到一个可能解),将当前装入背包物体的总价值CP_Total与之前搜索到的可能解的总价值P_Total进行比较,P_Total = max(CP_Total,P_Total),更新可能解X[],向上回溯:沿着空间树的右分支向上搜索至左分支结点(更新当前重量CW_Total,当前价值CP_Total,搜索解Y[]),将此物体移出背包(搜索左分支结点即此物体的右分支树),试探下一个物体;

 

3.回溯到第0个物体时,已经搜索完整个空间树,搜索过程结束,此时的P_Total为最大价值。

 

结论:算法效率差,每次搜索时一定要搜索至叶子结点才结束此次搜索,即一定要到达叶子结点后才进行回溯。进入右分支搜索时,可以通过条件判断是继续试探下一个物体还是直接进行回溯(即结束本次搜索)。

 

方案二:

 

1.将物体装入背包(搜索此物体的左分支),直到第i个物体不能装入时,对P_est(如果进入右分支搜索可能获得的最大值,P_est = cleft*p[i]/w[i])和之前搜索到的可能解的总价值P_Total进行比较。

 

2.如果P_est > P_Total,即进入第i 个物体的右分支继续搜索,保存当前重量CW_Total,当前价值CP_Total,搜索解Y[]。如果没有搜索完第n个物体,则继续试探下一个物体。如果搜索完第n个物体(即已到达空间树的叶子结点,搜索到一个可能解),将当前价值CP_Total与之前搜索到的可能解的总价值P_Total进行比较,P_Total = max(CP_Total,P_Total),更新可能解X[],向上回溯:沿着空间树的右分支向上搜索至左分支结点(更新当前重量CW_Total,当前价值CP_Total,搜索解Y[]),将此物体移出背包(搜索左分支结点即此物体的右分支树),试探下一个物体。回溯到第0个物体时,已经搜索完整个空间树,搜索过程结束,此时的P_Total为最大价值;

 

3.如果P_est < P_Total,不进入第i 个物体的右分支继续搜索,直接向上回溯:沿着空间树的右分支向上搜索至左分支结点(更新当前重量CW_Total,当前价值CP_Total,搜索解Y[]),将此物体移出背包(搜索左分支结点即此物体的右分支树),试探下一个物体。回溯到第0个物体时,已经搜索完整个空间树,搜索过程结束,此时的P_Total为最大价值。

 

结论:较方案一效率提高,利用估计最大值P_est判断是否进入空间树的右分支进行搜索,减少了访问空间树的结点的个数,提高搜索效率。

 

 

回溯法(递归回溯)

 

void backtrace(int i)    //递归搜索空间树

{

      //递归出口

      //如果搜索完第n个物体(即到达叶子结点)

      //记录当前最优值,return

 

 

      //如果能装入第i个物体

      //装入第i个物体(搜索第i个物体的左分支)

      //递归搜索第i+1个物体

      //1.右分支的估计最大值小于当前最优值;2.搜索完第n个物体

      //这两种情况都能停止递归,开始回溯

      //回溯,移出第i个物体(搜索左分支结点即第i个物体的右分支树)

 

      //1.如果第i个物体不能装入;2.回溯,移出第i个物体

      //这两种情况均要试探搜索第i 个物体的右分支树

      //如果沿着右分支搜索的可能最大值大于当前最优值

      //递归搜索第i+1个物体(搜索第i 个物体的右分支)

 

}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回溯法解0_1背包问题时,会用到状态空间树。在搜索状态空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。当右子树有可能包含最优解时才进入右子树搜索,否则将右子树剪去。设r是当前剩余物品价值总和;cp是当前价值;bestp是当前最优价值。当cp+r≤bestp时,可剪去右子树。计算右子树中解的上界可以用的方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包。由此得到的价值是右子树中解的上界,用此值来剪枝。 为了便于计算上界,可先将物品依其单位重量价值从大到小排序,此后只要顺序考察各物品即可。在实现时,由MaxBoundary函数计算当前结点处的上界。它是类Knap的私有成员。Knap的其他成员记录了解空间树种的节点信息,以减少函数参数的传递以及递归调用时所需要的栈空间。在解空间树的当前扩展结点处,仅当要进入右子树时才计算上界函数MaxBoundary,以判断是否可以将右子树减去。进入左子树时不需要计算上界,因为其上界与父结点的上界相同。 在调用函数Knapsack之前,需要先将各物品依其单位重量价值从达到小排序。为此目的,我们定义了类Objiect。其中,运算符与通常的定义相反,其目的是为了方便调用已有的排序算法。在通常情况下,排序算法将待排序元素从小到大排序。 在搜索状态空间树时,由函数Backtrack控制。在函数中是利用递归调用的方法实现了空间树的搜索
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值