回溯法-01背包问题之中的一个:递归模式_yuxiaoyu.的博客-程序员秘密

技术标签: 数据结构与算法  

一、回溯法

回溯法是一个既带有系统性又带有跳跃性的搜索算法。

它在包括问题的全部解的解空间树中依照深度优先的策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一节点时,总是先推断该节点是否肯定不包括问题的解。假设肯定不包括。则跳过对以该节点为根的子树的系统搜索,逐层向其原先节点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。

运用回溯法解题通常包括下面三个步骤:

· 针对所给问题,定义问题的解空间;

· 确定易于搜索的解空间结构。

· 以深度优先的方式搜索解空间,而且在搜索过程中用剪枝函数避免无效搜索。


二、01背包问题描写叙述

01背包问题,即向容量为M的背包装载物品,要么放入要么不放入。从n个物品中选取装入背包的物品,物品i的重量为Wi。价值为Pi。最佳装载指装入的物品价值最高,即∑PiXi(i=1..n)取最大值。约束条件为∑WiXi≤M且Xi∈[0,1](1≤i≤n)。

在这个表达式中,需求出Xi的值。

Xi=1表示物品i装入背包。Xi=0表示物品i不装入背包。

· 即推断可行解的约束条件是:∑WiXi≤M(i=0..n)。Wi>0,Xi∈[0,1](1≤i≤n)

· 目标最大值:max∑PiXi(i=0..n-1),Pi>0,Xi=0或1(0≤i<n)

0/1背包问题是一个自己选取问题,适合于用子集树表示0/1背包问题的解空间。

在搜索解空间树时,仅仅要左儿子节点是一个可行节点。搜索就进入左子树。在右子树中有可能包括最优解才进入右子树搜索,否则将右子树剪去。


三、关于剪枝函数

设当前剩余物品价值总和为r。当前结点x价值为cp。当前x结点上界函数值为bp。

L为当前已搜索到的答案结点中受益的最大值。当cp+r=bp<L时可剪去以X为根的子树。

计算右子树中解上界方法是将剩余物品按单位重量价值排序,一次放入物品直至装不下为止,再装入部分未装入物品直至装满背包。由此得到的价值是右子树解上界。

四、递归实现

例如以下图1所看到的为01背包问题递归实现的示意图。图2是01背包问题递归实现的流程图。描写叙述了代码实现方案。


                                 

图1 01背包问题递归描写叙述图                                     图2 01背包问题递归实现流程图


图1比較easy理解,是否已拿完物品也就是i<n(i是当前物品序号。n是物品总数目)是否成立,假设成立则递归结束并打印输出路径。

假设i<n则推断第i个物品是否能放入背包,假设不能放入。则考虑放置i+1个物品。假设能放入还存在当前第i个放入和不放入两种情形后对第i+1个的影响。

注意在“放入还是不放入”的部分可考虑增加剪枝函数。

五、递归的代码实现


代码1 Main函数測试代码:

public static void Main (string[] args)
		{
            Obj[] objs = new Obj[4];
            objs[0] = new Obj() { Weight = 7, Price = 42 };
            objs[1] = new Obj() { Weight = 3, Price = 12 };
            objs[2] = new Obj() { Weight = 4, Price = 40 };
            objs[3] = new Obj() { Weight = 5, Price = 25 };

            Backtracking_Recursion1 r = new Backtracking_Recursion1();
            r.W = 10;
            r.objs = objs;
            r.Backtracking(0);

            Console.Read();
		}

代码2Obj物品代码

public class Obj
    {
        /// <summary>
        /// 物品重量
        /// </summary>
        public int Weight
        {
            get;
            set;
        }
        /// <summary>
        /// 物品价值
        /// </summary>
        public int Price
        {
            get;
            set;
        }
        /// <summary>
        /// 该物品是否放入包内
        /// </summary>
        internal bool Selected
        {
            get;
            set;
        }
    }


代码3递归实现01背包问题

class Backtracking_Recursion1
    {
        #region field
        protected int m_currentWeight = 0;
        protected int m_currentPrice = 0;
        #endregion
        #region property
        /// <summary>
        /// 背包容量
        /// </summary>
        /// <value>默认20</value>
        public int W
        {
            get;
            set;
        }

        public int n
        {
            get
            {
                return objs == null ?

0 : objs.Length; } } /// <summary> /// 物品,包括重量/价值和数量 /// </summary> /// <value>The objects.</value> public Obj[] objs { get; set; } #endregion public void Backtracking(int i) { if (i >= n) { Printing(); return; } if (objs[i].Weight + m_currentWeight <= W) { m_currentWeight += objs[i].Weight; m_currentPrice += objs[i].Price; objs[i].Selected = true; Backtracking(i + 1); m_currentPrice -= objs[i].Price; m_currentWeight -= objs[i].Weight; } objs[i].Selected = false; Backtracking(i + 1); } /// <summary> /// 输出路径 /// </summary> protected void Printing() { Console.Write("<"); for (int i = 0; i < objs.Length; i++) { Console.Write(objs[i].Selected ?

"1 " : "0 "); } Console.WriteLine(">, price: " + m_currentPrice.ToString() + "\t weight: " + m_currentWeight.ToString()); } }




六执行结果


注:

1 代码3中Printing()函数调用后可推断并记录最优路径;

2 下文将讲述01背包问题回溯法的顺序执行方法。并通过模板模式整合两种不同的实现方案。


转载于:https://www.cnblogs.com/xfgnongmin/p/10619311.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30892763/article/details/94840484

智能推荐

机器学习/深度学习/自然语言处理学习路线_FishBear_move_on的博客-程序员秘密

原文地址:http://www.cnblogs.com/cyruszhu/p/5496913.html未经允许,请勿用于商业用途!相关请求,请联系作者:[email protected]转载请附上原文链接,谢谢。 机器学习/深度学习/自然语言处理学习路线 1 基础l  Andrew NG 的 Machine Learning视频。连接:主页,资料。 l  2

shell除法计算_shell 除法取整_JoeBlackzqq的博客-程序员秘密

From: http://5iwww.blog.51cto.com/856039/270119shell计算中使用除法,基本默认上都是整除。比如:num1=2num2=3num3=`expr $num1 / $num2`这个时候num3=0 ,是因为是因为expr不支持浮点除法解决的方法:num3=`echo "sclae=2; $num1/

软件运维常用工具_软件运维工具_ejinxian的博客-程序员秘密

一、搜索 1、查找本地文件存放位置 :Everything软件 2、端口查看工具:cports二、文件 1、文本查看工具、Notepad 2、日志工具:eDiary 3、文件对比:BCompare三、文件 1、Java反编译工具:jdryjgui 2、抓包工具:Wireshark 、IE浏览器http抓包工具:HttpAnalyzerFull_V7、httpwatch 3、webService接口调用工具:SoapUI 4、sv

VC++中使用使用winnet类获取网页内容_c++读取不同操作系统中的网页_等风来啊的博客-程序员秘密

 2005-09-01VC++中使用使用winnet类获取网页内容 - [VC专栏]微软提供的Winnet类是一个应用层的网络通信组件,它可以使你的应用程序很容易的实现http、ftp、gopher等协议而不需要你去深入的了解协议本身的规范。而之前,如果要想做类似的应用,我们必须了解socket编程并且要对协议本身非常熟悉,哪怕是一个非常非常简单的程序。下面是codegur

free5GC — 部署端到端 5G 实验网络_free5gc仿真实现5g专网_范桂飓的博客-程序员秘密

目录文章目录目录free5GC部署 free5GC 核心网部署拓扑前期准备执行部署测试验证UE/RAN 模拟器创建 ueramsim VM安装 UERANSIM安装 free5GC WebConsole对接 free5GC 和 UERANSIMfree5GC 配置UERANSIM 配置注册 UE测试 free5GC + UERANSIMfree5GC官方网站:https://www.free5gc.org/Github:https://github.com/free5gc官方文档:https:/

随便推点

ArcGIS 发布本地DEM服务_biandongwen6125的博客-程序员秘密

文章说明:本文是在项目过程中遇到问题,请教ESRI官方博客之后,进行整理。在项目过程中,原来用的DEM一般都在CS程序中使用,或者BS用在线的DEM即可,由于项目的特殊性,需要BS使用高精度DEM,在线DEM进度不够,只能发布本地DEM,但是发现ESRI没有提供专门发布DEM服务的工具,只有发布影像和地图的服务,于是就网上找资料,Email官方,给出的答案是,当前版本通过影像服务来发布DEM服务。...

【超好玩的路由环路系列】4——两个标准的战争:OSPF计算环路_路由表 intra area_网络之路Blog的博客-程序员秘密

OSPFV2的RFCOSPFV2在发展的过程经过了很多次改进,其中比较重要的两个标准是RFC1583和RFC2328。这两个标准在计算路由的时候使用的计算方法不一样。华为的VRP默认是开启了兼容RFC1583的功能,即默认采用最小COST来选路,如果部分路由器关闭了RFC1583兼容能力,OSPF在选路的时候还会参考区域类型等因素(如它会优先经过普通区域而不是骨干区域)可能会导致网络产生环路。本实验就主要用来理解“取消兼容RFC1583引发环路”这个知识点。二、实验拓扑三、基础配置—.

jtwig-spring-boot-starter ,Defining prefix/suffix of the resolver, resource not found_spring boot jtwig_blueriver1125的博客-程序员秘密

jtwig-spring-boot-starter ,Defining prefix/suffix of the resolver,resource not found代码地址:码云 最近接触到Jtwig模板引擎,遇到一个问题。想设置自己的 viewResolver, 设置之前我们先看看Jtwig源码中默认的 viewResolver的prefix/suffix配置。如上图,在jtwig-sp

Linux 配置git同步GitHub代码_linux同步git代码_刘泓君的博客-程序员秘密

因为我复制到服务器的文件夹本来就同步了GitHub,所以直接git status查看状态即可。

SVM实战之垃圾邮件过滤_luchi007的博客-程序员秘密

SVM作为机器学习里面的经典算法在实际中一直被广泛采用,而且其准确性也是非常之高,特别是在引入了核函数之后对识别性能变得非常高。说明:本文不打算就SVM原理就深入分析,虽然对其原理略懂一二,但是对于SMO算法的理解确实比较浅,所以也不打算班门弄斧,略微介绍,本文重点在于SVM的应用,也就是对垃圾邮件的文本分类 关于支持向量机的原理性分析在CSDN上有July大神的博客 :http://

深入理解C指针的奥妙(转)_深入理解c指针的奥秘_GXZheng1985的博客-程序员秘密

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。 要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的 类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。   先声明几个指针放着做例子:   例一:   (1)int*ptr;   (2)char*ptr;   (3)int**ptr;   (4)int(*ptr)[3];

推荐文章

热门文章

相关标签