回溯法解背包问题分析

先亮出题目:

一,背包问题 及 回溯法解其问题的伪代码

二,赋值后的具体实例

三,如何看懂伪代码

(1)真正了解回溯法的核心思想

我总结的回溯法解题步骤:

<1>先找出第一个解

<2>回溯

(2)回溯法核心思想 + 伪代码 + 图9-5 树结构来分析

四,伪代码代入值解析

核心:先找到第一个解,再回溯。
cw=0;//背包当前重量 初始值
cp=0;//背包当前价值 初始值
k=1;//第一个物品

n=8;//共8个物品
W=110
第一步:得出第1个可行解:
(1)k=1
k=1 <=8  and  0+1<110  //如果把第1个物品放入背包中,背包中物品重量1<背包容量110  可放入
   cw=0+1=1;  //把第1个物品放入背包后,目前背包重量=1
   cp=0+11=11;  //把第1个物品放入背包后,目前背包价值=11
   Y[1]=1;  //第1个物品放入背包中,则给Y[1]赋值为1
   K=1+1=2;  //尝试放第2个物品
(2)k=2
K=2 <=8  and 1+11<110  //如果再把第2个物品放入背包中,背包中物品重量12<背包容量110  可放入
   cw=1+11=12;   //把第2个物品放入背包后,目前背包重量=12
   cp=11+21=32; //把第2个物品放入背包后,目前背包价值=32
   Y[2]=1; //第2个物品放入背包中,则给Y[2]赋值为1
   K=2+1=3; //尝试放第3个物品
(3)k=3
K=3 <=8 and 12+21=33<110  //如果把第3个物品放入背包中,背包中物品重量33<背包容量110  可放入
     cw=12+21=33;  //把第3个物品放入背包后,目前背包重量=33
     cp=32+31=63;  //把第3个物品放入背包后,目前背包价值=63
     Y[3]=1;  //第3个物品放入背包中,则给Y[3]赋值为1
     K=3+1;  //尝试放第4个物品
(4)k=4
K=4<8  and 33+23=56  //如果把第4个物品放入背包中,背包中物品重量 56<背包容量110  可放入
     cw=33+23=56;   //把第4个物品放入背包后,目前背包重量=56
     cp=63+33=96;  //把第4个物品放入背包后,目前背包价值=96
     Y[4]=1;   //第4个物品放入背包中,则给Y[4]赋值为1
     K=4+1;  //尝试放第5个物品
(5)k=5
K=5 <=8  and  56+33=89<110  //如果把第5个物品放入背包中,背包中物品重量89<背包容量110  可放入
cw=56+33=89;  //把第5个物品放入背包中,目前背包重量=86
cp=96+43=139; //把第 5 个物品放入背包中,目前背包价值=139
Y[5]=1;  //第5个物品放入背包中,则给Y[5]赋值为1
K=5+1;  //尝试放第6个物品
(6)k=6
K=6 <=8  and  89+43=132>110  //如果把第6个物品放入背包中,背包中物品重量132>背包容量110  不可放入
    Y[6]=0; //第6个物品不能放入背包中,则给Y[6]赋值为0

BOUND(139,89,6,110)=139 > fp=-1
K=6+1=7
(7)k=7 <= 8 and 89+45 > 110  //如果把第7个物品放入背包中,背包中物品重量 134 > 背包容量110   不可放入
Y[7]=0; //第7个物品不能放入背包中,则给Y[7]赋值为0
BOUND(139,89,7,110)=139 > fp=-1
K=7+1
(8)k=8 <=8 and 89+55>110  //如果把第8个物品放入背包中,背包中物品重量 144 > 背包容量110  不可放入
  Y[8]=0; //第8个物品不能放入背包中,则给Y[8]赋值为0
     BOUND(139,89,8,110)=139 > fp=-1
     K=8+1
(9)k=9 >n=8
Fp=cp=139;
Fw=cw=89;
K=8;
X=[1,1,1,1,1,0,0,0];
输出第1个可行解X=[1,1,1,1,1,0,0,0]

第二步:回溯 得出第2个解
此时k=8
BOUND(139,89,8,110)=139 <=  fp=139   //前8个物品分别已经确定了是否放入
  k=8-1
 k=7 != 0 and  Y[7]!=1
  k=7-1
k=6!=0 and Y[6]!=1
 k=6-1
k=6!=0 and Y[5]=1
   Y[5]=0
   cw=89-33=56
   cp=139-43=96

BOUND(96,56,5,110)=149 >= fp=139   //前5个物品分别已经确定了是否放入 1,1,1,1,0 计算后3个物品是否放入
   K=5+1
K=6 <=8  and  56+43=99<=110
   cw=56+43=99
   cp=96+53=149
   Y[k]=1
   K=6+1
K=7 <= 8 and 99+45 > 110
  Y[7]=0
BOUND(149,99,7,110)=149 > fp=139
  K=7+1
K=8 <=8  and 99+55>110
  Y[8]=0
BOUND(149,99,8,110)=149 > fp=139
  K=8+1
K=9>8
Fp=cp=149
Fw=cw=99
K=8
X=Y=[1,1,1,1,0,1,0,0]
输出第2个可行解X= [1,1,1,1,0,1,0,0]
………继续回溯得到第3个解
………………………….第4个解
…………………………..

五,总结

文字语言表达能力差,但自认为回溯法的背包问题已经研究通了。对于算法相当薄弱的我,突然对这部分有了较大兴趣,近几天在研究其他算法,略懂皮毛。有意者可面对面交流。

回溯法解背包问题分析

时间: 2024-12-24 03:33:48

回溯法解背包问题分析的相关文章

利用回溯法求解背包问题

最近看完了利用回溯法求八皇后问题,最后成功求解到92种解法,然后在看利用贪心求解背包问题,突然想到其实也可以利用回溯法求解背包问题,本质上回溯法是一个穷举的方式在求. 回溯法求解出的结果肯定是正确的,这也可以验证自己所写的贪心算法的正确性. 问题描诉: 设定Wmax为最大重量,W[](0~n-1)为编号0~n-1的货物重量,V[](0~n-1)为其价值,x[]为其中解, 在wn=ΣXi*Wi<Wmax的条件下,求Vmax=ΣXi*Vi. 代码如下: //全局变量最大价值int maxvalue=

回溯法-01背包问题之一:递归模式

一.回溯法 回溯法是一个既带有系统性又带有跳跃性的搜索算法.它在包含问题的所有解的解空间树中按照深度优先的策略,从根节点出发搜索解空间树.算法搜索至解空间树的任一节点时,总是先判断该节点是否肯定不包含问题的解.如果肯定不包含,则跳过对以该节点为根的子树的系统搜索,逐层向其原先节点回溯.否则,进入该子树,继续按深度优先的策略进行搜索. 运用回溯法解题通常包含以下三个步骤: · 针对所给问题,定义问题的解空间: · 确定易于搜索的解空间结构: · 以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函

回溯法-01背包问题之二:顺序执行模式

上文已讲述了回溯法以及01背包问题的原理,本文讲述如何顺序执行解决01背包问题以及通过模板模式重构软件. 一.顺序执行流程图 图1无剪枝函数的01背包问题顺序执行算法流程图 图2 有剪枝函数的01背包问题顺序执行算法流程图 无剪枝函数是通用的深度遍历算法,为了减少搜索深度可通过剪枝函数处理完全不可能的分枝.与递归方案的区别主要表现在i>=n后需要"回溯",即用后进先出的方式将物品逐个拿出. 二.执行代码 递归与顺序执行方法仅仅是实现方法Backtracking(int i)不同,

八皇后问题-回溯法解

八皇后问题:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. int g_number = 0;? //多少种摆放方法?void EightQueen(){? ?const int queens = 8;? //棋盘大小?? ?int ColumnIndex[queens];? //列索引?//遍历行? ?for(int i = 0; i < queens; ++ i)?? ? ? ?ColumnIndex[i] = i;

暴力回溯法 解八皇后

国际象棋 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. public class _8Queen { //回溯法,暴力解8皇后 private static int ways = 0; //返回解法个数 public static int f8queen() { int[][] board = new int

每天刷个算法题20160519:回溯法解八皇后

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51502622 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西

回溯法--0-1背包问题

算法描述: 0-1背包的回溯法,与装载问题的回溯法十分相似.在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树.当右子树中有可能包含最优解时才进入右子树进行搜索.否则将右子树剪去. 计算右子树上界的更好算法是: 将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包. 算法实现: 由Bound函数计算当前节点处的上界. 类Knap的数据成员记录解空间树的节点信息,以减少参数传递及递归调用所需的栈空间. 在解空间树的当前扩展结点处,仅当要进

回溯法解0-1背包问题(王晓东算法例题)

给定n种物品和一背包.物品i的重量是wi,其价值为vi,背包的容量为C.问应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 整个解的空间相当于一个二叉树,左边是0,代表不取这个物品,右边是1,代表取这个物品,然后进行dfs,回溯的时候修改. 注意,这里应该有两个剪枝,我这里只写了一个. #include<iostream> #include<string> #include<cstring> using namespace std; int n,TotCap,

回溯法解数独题

近段时间用到回溯算法的地方比较多,对算法的理解也有深入.今天偶然发现一张照片,是高中时未做完的一道数独题.当时用的是"候选余数法",之后由于太麻烦,就没有做完.不过当时截图保存了,今天突然看到.那时候刚学完C语言,对汉诺塔递归都不是太理解,所以就一直拖到现在. 用C++做的,代码如下 #include<iostream> usingnamespace std;   intsudoku[9][9]={0};   //判断填在空白位置的数字在行.列上是否符合要求 boolJud