回溯法:以深度優先方式系統搜索問題的解
在問題的解空間樹中,按深度優先策略,從根節點出發搜索解空間樹
- 當搜索到解空間樹的任一結點時,判斷該結點是否包含問題的解
- 如果確定不包含,則跳過對以該結點為根的子樹的搜索,逐層向其祖先結點回溯;(剪枝)
- 否則,進入該子樹,繼續深度優先搜索;
求解問題的性質
- 求問題的所有解時,要回溯到根,且根節點的所有子樹都被搜索后才結束
- 求問題的一個解時,只要搜索到問題的一個解即可
回溯法的算法框架
問題的解空間
- 定義:問題的解空間至少應包含問題的一個最優解
- 組織:通常組織為樹或圖的形式——有利於回溯法對整個解空間的搜索
回溯法的基本思想
- 確定解空間的組織結構
- 從開始結點(根結點)出發,深度優先搜索整個解空間。(這個開始結點成為活結點,也為當前的擴展結點)
- 在當前擴展結點處,向縱深方向搜索一個新結點。(這個新結點成為活結點,也為當前的擴展結點)
- 如果不能向縱深方向搜索了,則當前結點成為死結點。並且往回移動(回溯)到最近的活結點處
- 回溯法按上述方式遞歸地在解空間中搜索,直到找到所要求的解或解空間中無活結點為止
如何避免回溯法的無效搜索
剪枝函數:
- 用 約束函數 在擴展結點處剪去不滿足約束的子樹——0-1背包問題
- 用 上界函數 剪去得不到最優解的子樹——TSP問題
遞歸回溯
void backtrack(int t) // 遞歸深度t
{
if(t > n) // 最大深度n
output(x);
else
for(int i = f(n, t); i <= g(n, t); ++i)
{ // 在當前擴展結點處未搜索過的子樹
x[t] = h(i);
if(constrain(t) && bound(t)) // 約束函數 和 上界函數
backtrack(t+1);
}
}
迭代回溯
void iterativeBacktrack()
{ // 采用樹的非遞歸深度優先遍歷(樹的遍歷)
stack<T> s; // 存結點的堆棧
T p = t; // 當前擴展結點p,根結點t
while(!s.empty())
{
for(int i = 0; i < p.child.size(); ++i)
{ // 在當前擴展結點處未搜索過的子樹
d = p.child[i]; // 子樹結點d
if(constrain(d) && bound(d)) // 約束函數 和 上界函數
s.push(d);
}
p = s.top();
s.pop();
}
}
子集樹和排列樹
-
子集樹
當所給問題是從n個元素的集合S中找出S滿足某種性質的子集時(選或不選某個結點),相應的解空間樹被稱為子集樹。
如0-1背包問題,這類問題通常有2n個葉結點,其結點總數為2n+1-1。
遍歷子集樹需要Ω(2n)計算時間
-
排列樹
當所給問題是確定n個元素滿足某種性質的排列時,相應的解空間樹被稱為排列樹。
如旅行商問題TSP,這類問題通常有n! 個葉結點
遍歷排列樹需要Ω(n!)計算時間

實例分析
旅行商問題 (排列樹)
- 問題描述:
某銷售商要到若干個城市去推銷商品,已知各城市之間的路程(或費用)。要求為給旅行商選擇一條從駐地出發的路徑,經過每個城市一次,最后返回駐地,使得該路徑(或總的旅費)最短(或最小)。
- 問題分析:
為NP難問題。設𝐺=(𝑉,𝐸)是一個帶權圖。圖中各邊的權為正數。圖的一條周游路線是包括𝑉中的每個頂點在內的一條回路。周游路線的費用是這條路線上所有邊的權之和。——旅行商問題就是要在圖𝐺中找出費用最小的周游路線。
- 實例分析:



對於n = 4的TSP問題,可能周游的路線有6條。
對於n = N的TSP問題,可能周游路線有(N-1)!條
- 回溯法求解過程:


- 剪枝函數的引入:
采用當前已知的最優解(費用X)為標准,若當前路徑長度 ≥ X,則表明以此結點為根結點的子樹中不包含最優解,將子樹中所有結點都設置為死結點,並向當前結點的最近祖先結點回溯。
- 時間復雜度及算法:
O(n!)
常用TSP解決方案:遺傳算法;模擬退火;神經網絡;並行算法
騎士巡游問題(子集樹)
符號三角形問題(子集樹)
N皇后問題(子集樹)
最大團問題(子集樹)
圖的m着色問題(子集樹)
圓排列問題(排列樹)
電路板排列問題(排列樹)
連續郵資問題
回溯法效率分析
影響因素
- 產生 狀態點x[k] 的時間
- 滿足顯約束的 狀態點x[k] 的個數
- 計算約束函數constrain的時間
- 計算上界函數bound的時間
- 滿足約束函數和上界函數的所有結點個數
解空間的結構一旦確定,前3個因素就可以確定,剩下的就是考慮回溯過程中生成的結點個數
重排原理
在搜索試探時,選取x[i]的值順序是任意的。在其他條件相當的前期下,讓可取值最少的x[i]優先有效。這樣,在低層剪枝時,可以剪去更多的子樹,可提高回溯法效率。
概率方法估計將產生的結點數
原因:
對兩個非常相近的實例,其產生的結點數也會存在很大的差別
方案:
在解空間樹上產生一條隨機路徑,然后沿該路徑估算解空間中滿足約束條件的結點數m
多選取幾條不同的路徑,分別計算m,然后平均,估算更准確
小結
-
回溯法的基本思想
-
問題解空間的定義和組織
-
剪枝函數的設計
-
掌握利用回溯法求解問題的方法
-
效率分析
PS: 本節內容偏於設計,於《算法導論》中無本章節,用於補充