0/1背包问题-回溯法

来源:互联网 发布:关于大数据的股票 编辑:程序博客网 时间:2024/05/16 01:13

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

 

回溯法(循环迭代回溯)

 

 

方案一:

 

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 个物体的右分支)

 

}

 

 

 

原创粉丝点击