回溯法——求解0-1背包问题

         以前研究过一个简单的N皇后问题,对回溯法也有了个模糊的认识,大致理解就是:先一直做某件事,当完成某个条件时或者是触犯某个条件时,再返回到最近的一个类似还原点的地方。

       在用回溯法求解0-1背包问题的时候,主要遇到三个相对难解决的问题:1,什么是界限函数;2,什么时候用它;3,回溯到哪儿。

   什么是界限函数?

        如下图:

            当我们身在一棵搜索空间树中,站在一个K点举棋不定的时候,我们可以用它估算如果我们继续向下走,我们走完本段路会获得的总价值。假设我们现在有一个最大解,当我用界限函数算出一个价值后和我当前的最大解比较,如果能获得更大利益,我们选择继续向下走,如果不能,果断放弃。

         从下图中的伪代码可以看出,我们计算后半段最大价值的时候,使用的还是一个贪心算法,虽然分割的情况是不被允许的,但是我们可以用这个结果来进行估算。

       

        

回溯法得到的搜索空间树:

     

            

       

    什么时候使用界限函数?

                

       数学一点儿的说法是:当X[i]=0时。

 

   通俗一点说:当进入右结点的时候。

   如何回溯的问题?

        向上回溯到第一个不是0的结点(并且这个结点不是顶点)。

               

   求解思路

                

               如上图搜索树,在建立搜索树之前,我将所有的物品按照V/W(价值重量比)从大到小排序,然后从第一个开始,依次向背包(背包大小110)中放入,放到第6个的时候,这时候发现6太大了,不能装入了,这时候用界限函数判断下,如果继续下去,会获得的最大价值,得出这个价值后,和上几次查找得到的最大价值对比,但是因为我们在这之前还没有获得过别的解,所以界限函数再和最大价值的初值-1比较的时候,总是会选择继续。这样我们就得到了一个解139.然后我们回溯到第一个X[i]不等于0的地方,此处为X[5],然后将X[5]置为0,这时候X[5]置0了,我们就先用界限函数判断下X[6]到X[8]的情况,得出了个164.44,这个比我们上次得到的第一个解也是最大的解139大,说明向后继续,肯会出现一个比139还大的解,所以我们选择向后继续。。。。。。

               。。。。。。。。。

            但我们回溯到X[1]的时候,我们将X[1]置0,这时候用界限函数估算下物品2到物品8可能获得的最大价值,发现是155.11,比我们实际得到的最大解159还小,然后果断放弃,再向上回溯,发现这已经到了尽头了,然后停止。

                 

                  结合以前的N皇后问题,N皇后问题是我一行一行的放皇后,如果当下一行放到最后一个位置的时候还是会产生攻击,这时候我们就调整上一行皇后的位置,然后再回到本行从第一个开始放。对比0-1背包,这个是完成一次求解过程,然后就回溯继续求解。

            

            所以,回溯法是先一直做,做不下去了,然后才向回走。

     小结:

                    0-1背包问题的用回溯法解决最开始提出的三个问题挺关键的,试想,如果一个问题足够大的话,用界限函数能够砍掉很多不合条件的子节点,极大的提高了效率。

时间: 2024-10-24 17:35:08

回溯法——求解0-1背包问题的相关文章

struct-关于使用回溯法求解迷宫问题

问题描述 关于使用回溯法求解迷宫问题 #include using namespace std ; const int m = 4 , p = 4 ; struct offsets { int a , b ; char *dir ; }; offsets move[8] ; int Maze[m+2][p+2] ; int mark[m+2][p+2] ; int main (){ int i , j; int SeekPath (int x ,int y ) ; offsets move[8]

并行计算思考----回溯法求解数独问题

 1.Intel Parallel Studio 环境下的并行程序设计 书官方网站的详情页: http://www.wrox.com/WileyCDA/WroxTitle/Parallel-Programming-with-Intel-Parallel-Studio-XE.productCd-0470891653.html 可以下载相关代码 2.在使用并行计算来优化自己的串行程序之前,我们需要思考以下几个方面的问题 什么情况下需要并行? 并行能够带来多少性能的提升? 编码和调试的时间成本?

回溯法——求解N皇后问题

问题描述       八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上.可以把八皇后问题拓展为n皇后问题,即在n*n的棋盘上摆放n个皇后,使其任意两个皇后都不能处于同一行.同一列或同一斜线上.     问题分析       我们以最简单的4皇后问题分析,显然,为了使皇后不相互攻击,首先考虑每一行只能放一个皇后,我们以X[1,2,3-.N]代表此问题的解数组,X[N]代表在第N行第X[

java使用回溯法求解数独示例_java

复制代码 代码如下: import java.util.Calendar;import java.util.Date; public class Matrix {  private int matrix[][]; private long timeAfter=0;  private long timeBefore =0; public Matrix(int m[][]) {  matrix = new int[9][9];  for (int i=0; i<9 ; i++)   for(int

PHP回溯法解决0-1背包问题实例分析_php技巧

本文实例讲述了PHP回溯法解决0-1背包问题的方法.分享给大家供大家参考.具体分析如下: 这段代码是根据<软件设计师>教程的伪代码写的: 最麻烦的不是伪代码改成php,而是数组下标从0开始,及相应的下标判断问题: 带着调试输出一块写上 <?php $v_arr = array(11,21,31,33,43,53,55,65); $w_arr = array(1,11,21,23,33,43,45,55); $n = count($w_arr ); //测试输出 var_dump(bkna

回溯法 -数据结构与算法

1.回溯法算法思想:   定义:         回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为"回溯点". 1.回溯法适用:有许多问题,当需要找出它的解集(全部解)或者要求回答什么解是满足某些约束条件的最优解时,往往要使用回溯法. 2.有组织的穷举式搜索:回溯法的基本做法是搜索或者有的组织穷尽搜索.它能避免搜索所有的可能

C++回溯法实例分析_C 语言

本文实例讲述了C++的回溯法,分享给大家供大家参考之用.具体方法分析如下: 一般来说,回溯法是一种枚举状态空间中所有可能状态的系统方法,它是一个一般性的算法框架. 解向量a=(a1, a2, ..., an),其中每个元素ai取自一个有限序列集Si,这样的解向量可以表示一个排列,其中ai是排列中的第i个元素,也可以表示子集S,其中ai为真当且仅当全集中的第i个元素在S中:甚至可以表示游戏的行动序列或者图中的路径. 在回溯法的每一步,我们从一个给定的部分解a={a1, a2, ..., ak}开始

C语言使用回溯法解旅行售货员问题与图的m着色问题_C 语言

旅行售货员问题 1.问题描述: 旅行售货员问题又称TSP问题,问题如下:某售货员要到若干个城市推销商品,已知各城市之间的路程(或旅费),他要选定一条从驻地出发,经过每个城市一遍最后回到驻地的路线,使总的路线(或总的旅费)最小.数学模型为给定一个无向图,求遍历每一个顶点一次且仅一次的一条回路,最后回到起点的最小花费. 2.输入要求: 输入的第一行为测试样例的个数T( T < 120 ),接下来有T个测试样例.每个测试样例的第一行是无向图的顶点数n.边数m( n < 12,m < 100 )

PHP回溯法解决0-1背包问题实例分析

 这篇文章主要介绍了PHP回溯法解决0-1背包问题,实例分析了php回溯法解决背包问题的技巧,具有一定参考借鉴价值,需要的朋友可以参考下     本文实例讲述了PHP回溯法解决0-1背包问题的方法.分享给大家供大家参考.具体分析如下: 这段代码是根据<软件设计师>教程的伪代码写的: 最麻烦的不是伪代码改成php,而是数组下标从0开始,及相应的下标判断问题: 带着调试输出一块写上 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22