遞迴 回溯 裝載問題

2021-09-30 16:44:30 字數 2031 閱讀 9103

之前討論了最優裝載問題的貪心演算法,這裡討論最優裝載問題的乙個變形。

1、問題描述:

有一批共n個貨櫃要裝上兩艘載重量分別為c1和c2的輪船,其中貨櫃為wi,且

要求確是否有乙個合理的裝載方案可將這n個貨櫃裝上這2艘輪船?如果有,找出一種裝載方案。

例如,當n=3,c1=c2=50,且w=[10,40,40]時,可將貨櫃1和2裝上第一艘輪船,而將貨櫃3裝上第二艘輪船:如果w=[20,40,40],則無法將這3個貨櫃都裝上輪船。

輸入:貨櫃的個數n,第一艘船的載重量c1,各個貨櫃的重量wi

執行結果:

容易證明,如果乙個給定的裝載問題有解,則採用下面的策略可以得到最優裝載方案。

(1)首先將第一艘輪船盡可能裝滿;

(2)然後將剩餘的貨櫃裝上第二艘輪船。

將第一艘輪船盡可能裝滿等價於選取全體貨櫃的乙個子集,使該子集中貨櫃重量之和最接近c1,由此可知,裝載問題等價於以下特殊的0-1揹包問題:

2、演算法設計

用回溯法解裝載問題時,用子集樹表示其解空間顯然是最合適的。可行性約束函式可剪去不滿足約束條件

下面的解裝載問題的回溯法中,演算法maxloading返回不超過c的最大子集和。

演算法maxloading呼叫遞迴函式backtrack(1)實現回溯搜尋。backtrack(i)搜尋子集樹中第i層子樹。類loading的資料成員。記錄子集樹中結點資訊,以減少傳給backtrack的引數。cw記錄當前結點所對應的裝載重量,bestw記錄當前最大裝載重量。

在演算法backtrack中,當i>n時,演算法搜尋至葉結點,其相應的裝載重量為cw。如果cw>bestw,則表示當前解優於當前最優解,此時應更新bestw。

當i  <= n時,當前擴充套件結點z是子集樹中的內部結點。該結點有 x[i] = 1 和 x[i] = 0兩個兒子結點。其左兒子結點表示x[i] = 1的情形,僅當cw+w[i]<=c時進入左子樹,對左子樹遞迴搜尋。其右兒子結點表示x[i]=0的情形。由於可行結點的右兒子結點總是可行的。故進入右子樹時不需檢查可行性。

演算法backtrack動態的生成問題的解空間樹。在每個結點處演算法花費o(1)時間,子集樹中結點個數為

3、上界函式

對於前面描述的演算法backtrack,可以引入乙個上界函式,用於剪去不含最優解的子樹,從而改進演算法在平均情況下的執行效率,設z是解空間樹第i層上的當前擴充套件結點。cw是當前載重量,bestw是當前最優載重量;r是剩餘貨櫃的重量,即

在下面的改進演算法中,引入類loading的變數r,用於計算上界函式。引入上界函式後,在達到乙個葉結點時就不必再檢查該葉結點是否優於當前最優解。因為上界函式使演算法搜尋到的每個葉結點都是當前找到的最優解。雖然改進後的演算法的計算時間複雜度仍為

4、構造最優解

為了構造最優解,必須在演算法中記錄與當前最優值相應的當前最優解。為此,在類loading中增加兩個私有資料成員x和bestx。x用於記錄從根至當前結點的路徑;bestx記錄當前最優解。演算法搜尋到葉結點處,就修正bestx的值。.

template class loading

;//核心函式 對解空間樹回溯搜尋,求得最優值

template void loading::backtrack(int t)

r -= w[t];

//搜尋子樹,此時,t<=n時 當前擴充套件結點是子集樹中的內部結點

//該結點有x[i]=1和x[i]=0兩個兒子結點

if(cw + w[t] <= c) //搜尋左子樹x[i]=1

if(cw + r > bestw)

r += w[t];

}//負責對類的私有變數初始化,呼叫遞迴函式backtrack(1)實現回溯搜尋並返回最優值

template type maxloading(type *w, type c, int n, int *bestx)

八皇后問題 回溯 遞迴 回溯 非遞迴

八皇后問題 在8x8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。分析 我們可以嘗試在將第乙個皇后擺放在第0行第0列,為了不衝突,將第二個皇后擺放在第1行第3列 依次下去 然後發現第5行每個位置都有衝突,這說明上面4行肯定不能這麼擺放...

八皇后問題(遞迴,回溯)

八皇后問題是乙個以西洋棋為背景的問題 如何能夠在 8 8 的西洋棋棋盤上放置八個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行 縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題 這時棋盤的大小變為n n,而皇后個數也變成n。當且僅當 n 1 或...

遞迴 回溯 八皇后問題

八皇后 問題,是乙個古老而著名的問題,是回溯演算法 的典型案例。該問題是國際西洋棋棋手馬克斯 貝瑟爾於1848年提出 在8 8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法.輸入 無 輸出 8行8列的矩陣,0代表此處無皇后,1表示此處有...