經典演算法 回溯演算法

2021-09-25 05:37:05 字數 1957 閱讀 3657

回溯是遍歷搜尋空間所有可能組態的方法。這些組態也許代表物件的所有排列或這是構建物件集合的所有可能的方法(子集)。其他情況包括列舉乙個圖的所有生成樹,兩個節點的所有路徑或是把節點分類成不同顏色的所有不同的方式。

這些問題有乙個共同的難點就是我們必須每次產生乙個可能的組態。避免重複或遺漏組態的方法就是我們必須定義乙個系統性的產生組態的順序。我們把組合搜尋解作為乙個向量a=(a1,a2,...,an),向量元素ai來自有限子集s。這樣的向量也許表示乙個序列,元素ai是排列的第i個元素。或者,向量表示的是乙個子集s,ai代表空間中的第i個元素是否在子集s中。

在回溯演算法的每一步,我們都試圖通過在末尾新增其他元素來擴充套件乙個給定的部分解a=(a1,a2,...,ak)。在擴充套件之後,我們必須檢驗目前的部分解是不是符合條件的完整解:如果是,我們應該輸出或將解的數量加一(計數)。如果不是完整解,那麼我們應該驗證這個部分解有沒有可能擴擴充套件成為完整解。

回溯演算法構造了一顆部分解的樹,樹中每乙個節點代表了部分解。如果節點y是從節點x構造而來,那麼x與y之間就存在一條邊。這棵樹為思考回溯演算法提供了另乙個角度,構造解的過程實際上就是在這棵樹上進行深度優先搜尋遍歷。回溯演算法的結構如下所示:

1

bool finished = false; /*

是否獲得全部解?

*/2 backtrack(int a, int

k, data input)319

}20 }

這個演算法的應用程式部分包括5個子程式:

1  is a solution(a,k,input)  -這個布林函式驗證向量a的前k個元素能否構成乙個給定問題的完整解。最後乙個引數,input,允許我們像函式中傳遞其他必要的資訊。我們可以用它指定n——目標解的大小。

2  construct candidates(a,k,input,c,ncandidates)  根據目前狀態,構造這一步可能的選擇,存入c陣列,其長度存入ncandidates

3  process_solution(a,k,input)  對於符合條件的解進行處理,通常是輸出、計數等

4  make_move(a,k,input)和unmake_move(a,k,input)  前者將採取的選擇更新到原始資料結構上,後者把這一行為撤銷。

乙個關鍵問題是,當指定表示組合物件的狀態空間時,這個空間需要表示多少物件。比如,對於序列這樣乙個n元素集合,有多少個子集存在呢?當n=1時,只有兩個子集存在,即{}和。當n=2時,有4個子集存在,當n=3時有8個子集。所以對於n,有2n個子集存在。

每乙個子集可以用元素是否在其中來表示。為了構造所有2n個集合,我們建立乙個n元素的集合,其中ai的值表示第i個元素是否在給定的子集中。在一般的回溯演算法機制中,sk=(true, false)並且只要k=n時a就是乙個解。現在我們可以通過簡單的實現is_a_solution(), construct_candidates()以及process_solution().

由於每次for迴圈中a[k]=c[i],這是唯一的改動,並且在下次迴圈時會被覆蓋,不需要專門編寫make_move()和make_unmove()。

#include#include

#include

#define maxcandidates 100

bool is_a_solution(int *a, int k, int

n) void process_solution(int* a, int k, int

n) printf(

"}\n");

}void construct_candidate(int a, int k, int n, int c, int *ncandidates)

void backtrack(int* a, int k, int

n)

else

}}void generate_subsets(int

n) int

main()

經典演算法之回溯法

1 綜述 回溯法可以看成是蠻力法的公升級版,它從解決問題每一步的所有可能選項裡系統的選擇出乙個可行的解決方案。回溯法非常適合由多個步驟組成的問題,並且每個步驟都有多個選項。當我們在某一步選擇了其中乙個選項時,就進入下一步,然後面臨新的選項。我們就這麼重複選擇,直至到達最終的狀態。用回溯法解決的問題的...

經典演算法之回溯法

回溯演算法實際上乙個類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就 回溯 返回,嘗試別的路徑。回溯法是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,...

回溯演算法經典例子

例如,對於 n 3 的 01 揹包問題,可以用完全二叉樹表示其解空間 解空間樹的型別 子集樹 當所給問題是從 n 個元素的集合 s 中找出 s 滿足某種性質的子集時,相應的解空間樹稱為子集樹。void backtrack int t 排列樹 當所給問題是確定 n 個元素滿足某種性質的排列時,相應的解...