通過例子講解回溯法 分枝限界法

2021-08-20 19:37:58 字數 4285 閱讀 7839

1.寫在前面

這學期上演算法課,對分枝限界法這一章聽的似懂非懂。後來複習備考時,參考了王曉東老師的《計算機演算法設計與分析》,把這部分的原理徹底整明白了,在此與大家分析心得。我將結合自己的理解和書上的幾個例子,來具體說明回溯法和分枝限界法原理,實現**網上比比皆是,故不再贅述。

演算法整體而言,大致可以分為3類,基於規模、基於搜尋、隨機化。基於規模的演算法主要有分治、動態規劃、貪心演算法;基於搜尋的有回溯分枝限界法;隨機化嚴格來說是一種策略,能優化演算法的效能,主要有舍伍德演算法、拉斯維加斯演算法和蒙特卡洛。以上是「演算法設計與分析」這門課的體系,分枝限界法是基於搜尋的一種演算法,下面也會通過例項和回溯法進行對比,以說明二者的區別和聯絡。

2.例子一(0-1揹包問題)

對於n=3的0-1揹包問題,考慮以下例項:3個商品的重量weight=[16, 15, 15],對應的價值為value=[45, 25, 25],揹包允許裝入的總重量為c=30,優化目標是在揹包中裝入商品的重量不超過c的情況下,最大化裝入商品的價值。

先不考慮揹包重量的限制c,則每個商品有選擇裝入和不裝兩種可能,所以一共有2^3=8種選擇,即。大括號{}整體稱為解空間,其中每乙個小括號()為解向量,表示一種選擇,裡面有3個數,代表這種選擇中3個商品是否裝入揹包。0表示裝入,1表示不裝入。如(0, 0, 1)表示的情況是商品1、2均不裝入揹包,商品3裝入揹包,此時揹包裝入商品的總重量為15,總價值為25,且未超過揹包的重量限制值30。顯然(0, 1, 1)是本例中最優的選擇,即把商品2、3裝入揹包,商品1不裝,此時揹包裝入商品的總重量為30,總價值為50,且滿足重量限制的條件。

基於搜尋的演算法解決時,都要先寫出解空間和解向量,並以此生成解空間樹,如圖1所示。樹分枝上方的1表示選擇該商品放入揹包,0表示不選該商品。除了根節點,樹一共有3層,表示3個商品的選擇與否。當遍歷完所有葉節點,即得到了所有的結果。但是搜尋的順序如何確定呢?這就是回溯法和分枝限界的第一點區別。回溯法是以深度優先方式搜尋整棵樹,而分枝限界法是以廣度優先或以最小耗費來搜尋的。具體來說,分枝限界分為兩種:佇列式分枝限界優先佇列式分枝限界。這一點很重要,佇列式分枝限界(資料結構為佇列,先進先出)採用的是廣度優先的搜尋,優先佇列式分枝限界(資料結構為優先順序佇列,也能是其他的資料結構)採用的是優先順序高的優先搜尋,高優先順序的定義往往是最小耗費或最大效益。

先簡單介紹幾個概念,下面會用到。擴充套件節點:乙個正在產生兒子的節點;活節點:乙個自身已生成,但是其兒子節點還沒有全部生成的節點;死節點:乙個所有兒子節點已經產生的節點。

圖1 0-1揹包問題的解空間樹

2.1.回溯法

當然,可以設計更好的剪枝函式,來簡化搜尋的過程,提高演算法的效率,本文省去這一步驟。

2.2.佇列式分枝限界法

該方法是廣度優先搜尋。初始時,隊列為空,節點a為當前擴充套件節點。節點a的2個兒子節點b、c均為可行節點,所以把b、c按從左到右的順序加入列表中。由於a已經擴充套件出所有兒子節點,所以出隊。此時的活節點列表(可以看做是乙個佇列,左邊出隊,右側入隊)為,b和c哪個排在前面都行,不影響演算法,因為這兩種情況都屬於廣度優先搜尋。按先進先出的原則,下一擴充套件節點為b,擴充套件後得到節點d和e。但是節點d不是可行解,故捨去。此時的活節點列表為。接著c成為新的擴充套件節點,生成節點f、g。由於兩個節點都是可行解,所以此時的活節點列表為。再把e當做擴充套件節點,得到節點j、k。節點j不是可行解,捨去。節點k可行,且已到達葉節點,所以得到了暫時的最大揹包重量bestv=45和其對應的解向量(1, 0, 0),這時的活節點列表為。把f當做擴充套件節點,l和m均是可行解,且到達葉節點。l這個分枝的揹包重量為50>bestv,m分枝的揹包重量是25,所以更新bestv=50,更新解向量為(0, 1, 1),這時的活節點列表為。把g擴充套件成節點n和o。但是這兩個節點的揹包最大重量均未超過bestv,所以捨去。此時活節點列表為空,演算法結束,輸出最優值bestv和解向量。

2.3優先佇列式分枝限界法

優先佇列式分枝限界法首先要定義優先順序。0-1揹包問題主要有兩種優先順序定義的方法,一種是把已搜商品的最大價值定義為高優先順序;另一種是定義已搜的與未搜的可能放入的最大商品價值的和較高的擁有高優先順序。本例中採用第一種優先順序的定義方式。優先佇列式和佇列式分枝限界法的區別就在於活節點佇列中,節點的順序不同,優先佇列式節點的順序是按優先順序高低排序的,先搜優先順序高的,所以不一定是廣度優先搜尋;而佇列式是把一層搜完再搜下一層,屬於廣度優先搜尋。

優先佇列式採用的資料結構可以是優先順序佇列(如c++中的priority_queue)。初始時,隊列為空。擴充套件a,得到它的兩個兒子節點b和c。這兩個節點都是可行節點,加入到佇列中,節點a出隊。節點b獲得的價值是45,而節點c若選擇,獲得的價值是0,所以節點b的優先順序高於節點c,此時活節點列表為,b排在c前面是因為計算優先順序後b的大,此處二者順序不能換。b成為下一擴充套件節點,得到節點d和e。d不是可行解,捨去。e是可行解,加入活節點佇列,這時已搜揹包的總價值仍為45,活節點列表為,e節點的優先順序高於c的。接著擴充套件e,得到葉節點j和k。j不可行,捨去。k可行,且到達葉節點,得到了暫時的最大揹包重量bestv=45和其對應的解向量(1, 0, 0)。此時活節點列表為。擴充套件了c後,得到節點f和g。f的已搜商品的最大價值為25,g的最大價值為0,所以f的優先順序高於g,此時活節點列表為。擴充套件f,得到兩個兒子節點l和m。l的最大價值為50>bestv,所以更新bestv=50,更新解向量為(0, 1, 1)。在搜g的子節點,均未大於bestv。隊列為空,演算法結束。

3.例子二(旅行售貨員問題)

旅行售貨員問題是指某售貨員要到若干個城市去推銷商品,已知各個城市間的連線關係及路程(花費)。該售貨員要從某一給定的城市出發,選擇一條路徑,能途徑每乙個城市,最後返回到出發的城市,且總的路程(花費)最小。如圖2所示,1、2、3、4是四個城市,兩個城市間的數字是這兩個城市間的路程,如城市1與城市3之間的路程(花費)是6。序列1,2,4,3,1是一條可行路徑,對應於解空間樹中的a, b, c, g, m這條路徑。

圖2 旅行售貨員問題的解空間樹

3.1.回溯法

與0-1揹包的過程類似,回溯法會先一路搜尋到葉節點,即a->b->c->f->l,得到費用為59,暫時的bestv=59。之後返回到c,再搜尋a->b->c->g->m,費用為66>bestv,所以捨去。按部就班地搜尋後面的分枝,最終可以得到最優解:a->b->d->h->n,即從城市1->3->2->4->1。剪枝函式可以設計為剪去那些無法返回到城市1的分枝和費用超過bestv的分枝,以提高搜尋速度。

3.2.佇列式分枝限界法

初始時,把b當做擴充套件節點,活節點隊列為空。b擴充套件後,把節點c、d、e加入活節點列表,此時的活節點列表為。c成為下乙個擴充套件節點,擴充套件出f和g。之後依次擴充套件節點d和e,節點d、e擴充套件完後,活節點列表變為。f成為下一擴充套件節點。此時到達葉節點,得到暫時的bestv=59。之後g擴充套件為m,計算費用值為66,大於bestv,故捨去。後面的節點以此類推,直至活節點列表為空,演算法結束,輸出bestv=25和對應的路徑a->b->d->h->n。

3.3優先佇列式分枝限界法

優先順序定義為售貨員當前已經過城市的總花費。初始時,擴充套件節點b,得到3個兒子節點c、d、e。由於這3段路程的花費為30>6>4,所以活節點列表的順序為,左邊的優先順序高,先擴充套件。e擴充套件後,得到j和k,對應的費用為14和24,所以活節點佇列變為。接下去擴充套件節點d,得到節點h和i。從b到達h的費用為11,從b到達i的費用為26,所以活節點佇列變為。擴充套件h後,到達葉節點n,得到一條迴路1->3->2->4->1,bestv=25,此時活節點佇列變為。擴充套件k,得到另一條路徑,但其費用未低於25,捨去。之後擴充套件k,可行解費用超過bestv,捨去。擴充套件i,本身的費用已超過bestv,i及之後的節點均無需再計算,捨去。最後列表為空,輸出結果。

4.總結

通過以上兩個例項,回溯法和分枝限界法的演算法流程應該能大體掌握。當然,要深入了解這兩個演算法,仍需進一步學習如何構建解空間,是用排列樹還是子集樹、剪枝函式如何定義、如何程式設計實現等等不一而足。最後梳理一下回溯法和分枝限界法的主要區別。

求解目標:找出解空間中滿足條件的所有解;

搜尋方式:以深度優先的方式搜尋;

擴充套件方式:擴充套件節點基本不會一次產生所有兒子節點。

求解目標:找出解空間中滿足條件的乙個解,或者最優解;

搜尋方式:以廣度優先的方式或以最小耗費的方式搜尋;

擴充套件方式:活節點一旦產生擴充套件節點,則一次性產生其所有兒子節點。

分枝限界法 最優裝載問題

採用分枝限界法求解最優裝載問題。給出以下裝載問題的求解過程和結果 n 5,貨櫃重量為w 5,2,6,4,3 限重為 w 10。在裝載重量相同時最優裝載方案是貨櫃個數最少的方案。include include using namespace std define maxn 21 最多的貨櫃數 問題表示...

分枝 限界法的相關知識

定義 分支定界 branch and bound 演算法是一種在問題的解空間樹上搜尋問題的解的方法。但與回溯演算法不同,分支定界演算法採用廣度優 先或最小耗費優先的方法搜尋解空間樹,並且,在分支定界演算法中,每乙個活結點只有一次機會成為擴充套件結點。利用分支定界演算法對問 題的解空間樹進行搜尋,它的...

分枝限界法求TSP問題 C C

旅行商問題 tsp 給定一系列城市和每對城市之間的距離,求解訪問每一座城市一次並回到起始城市的最短迴路。它是組合優化中的乙個np困難問題,在運籌學和理論電腦科學中非常重要。這篇文章裡介紹一下基於分支限界法的tsp演算法。對於tsp,我們需要利用上界和下界來對bfs進行剪枝,通過不斷更新上界和下界,盡...