回溯法-01揹包問題之一:遞歸模式

一、回溯法

回溯法是一個既帶有系統性又帶有跳躍性的搜索算法。它在包含問題的所有解的解空間樹中按照深度優先的策略,從根節點出發搜索解空間樹。算法搜索至解空間樹的任一節點時,總是先判斷該節點是否肯定不包含問題的解。如果肯定不包含,則跳過對以該節點爲根的子樹的系統搜索,逐層向其原先節點回溯。否則,進入該子樹,繼續按深度優先的策略進行搜索。

運用回溯法解題通常包含以下三個步驟:

· 針對所給問題,定義問題的解空間;

· 確定易於搜索的解空間結構;

· 以深度優先的方式搜索解空間,並且在搜索過程中用剪枝函數避免無效搜索;


二、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比較容易理解,是否已拿完物品也就是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揹包問題回溯法的順序執行方法,並通過模板模式整合兩種不同的實現方案。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章