• 回溯-01背包问题之二:连续工作模式


    上面已描述回溯和01原理背包问题,本文介绍如何以解决运行01背包问题和由重建软件模板图案。

    一、运行流程图秩序


    图1无剪枝函数的01背包问题顺序运行算法流程图



    图2 有剪枝函数的01背包问题顺序运行算法流程图

    无剪枝函数是通用的深度遍历算法。为了降低搜索深度可通过剪枝函数处理全然不可能的分枝。与递归方案的差别主要表如今i>=n后须要“回溯”。即用后进先出的方式将物品逐个拿出。


    二、运行代码

    递归与顺序运行方法不过实现方法Backtracking(int i)不同,其余的全然一致。因此可将详细实现延迟至子类中。

    模板方法使得自雷能够改变一个算法的结构就可以重定义该算法的某些特定步骤。因此採用模板模式。类图结构如图3所看到的:

    图3 回溯法模板模式类图

    代码1 測试代码

    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 };
    
    
                AbsBacktracking r = new Backtracking_Nonrecursion();
    
                r.W = 10;
                r.objs = objs;
                Console.WriteLine("Nonrecursion Model:");
                r.Backtracking(0);
    
    
                Console.WriteLine("Recursion Model:");
                r = new Backtracking_Recursion();
                r.W = 10;
                r.objs = objs;
                r.Backtracking(0);
    
                
                Console.Read();
    		}


    代码2 抽象类 AbsBacktracking

    public abstract class AbsBacktracking
        {
            #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 abstract void Backtracking(int i);
            
    
            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() + " weight: " + m_currentWeight.ToString()); } }


    代码3 类Backtracking_Nonrecursion

    public class Backtracking_Nonrecursion:AbsBacktracking
        {
           
            public override void Backtracking(int i)
            {
                while (true)
                {
                    if (i < n)
                    {
                        if (m_currentWeight + objs[i].Weight <= W)
                        {
                            //将第i个物品放入包中
                            m_currentWeight += objs[i].Weight;
                            m_currentPrice += objs[i].Price;
                            objs[i].Selected = true;
                        }
                    }
                    else
                    {
                        //打印路径
                        Printing();
                        i--;
                        while (i >= 0 && !objs[i].Selected)
                        {
                            i--;
                        }
    
                        if (i < 0)
                        {
                            return;
                        }
                        else
                        {
                            //将i从包内拿出
                            m_currentWeight -= objs[i].Weight;
                            m_currentPrice -= objs[i].Price;
                            objs[i].Selected = false;
    
                            
                        }
    
                    }
                    i++;
                }
                
            }
    
        }



    代码4 代码片段Backtracking_Recursion

    public class Backtracking_Recursion :AbsBacktracking
    	{
    		public override 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);
    		}
    
    	}

    代码5 Obj代码片段

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

    三、执行结果:



    注:上述实现中没有加入剪枝函数功能,也没有加入推断最优路径功能,读者可继续优化。



    下载源码













    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    异常详细信息: System.Data.SqlClient.SqlException:过程或函数 需要参数 但未提供该参数。
    silverlight error message,ErrorCode:2254 ErrorCode: 1001
    每日英语 词汇
    每日词汇
    电子商务网站用户体验根据用户的习惯进行推荐
    刚做项目的时候
    silverlight 不可
    在Centos6上安装RabbitMQ的过程(有点坑)
    SpringBoot整合Redis
    在IDEA中创建工程并将工程添加至Git
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4843391.html
Copyright © 2020-2023  润新知