回朔法簡單總結

2021-08-06 06:18:59 字數 2480 閱讀 8550

冷血之心的部落格)

回溯法(探索與回溯法)是一種選優搜尋法,又稱為試探法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為「回溯點」。

在回溯法中,每次擴大當前部分解時,都面臨乙個可選的狀態集合,新的部分解就通過在該集合中選擇構造而成。這樣的狀態集合,其結構是一棵多叉樹,每個樹結點代表乙個可能的部分解,它的兒子是在它的基礎上生成的其他部分解。樹根為初始狀態,這樣的狀態集合稱為狀態空間樹。

回溯法解題的關鍵要素:

確定了問題的解空間結構後,回溯法將從開始結點(根結點)出發,以深度優先的方式搜尋整個解空間。開始結點成為活結點,同時也成為擴充套件結點。在當前的擴充套件結點處,向縱深方向搜尋並移至乙個新結點,這個新結點就成為乙個新的活結點,並成為當前的擴充套件結點。如果在當前的擴充套件結點處不能再向縱深方向移動,則當前的擴充套件結點就成為死結點。此時應往回移動(回溯)至最近的乙個活結點處,並使其成為當前的擴充套件結點。回溯法以上述工作方式遞迴地在解空間中搜尋,直至找到所要求的解或解空間中已無活結點時為止。

運用回溯法解題的關鍵要素有以下三點:

(1) 針對給定的問題,定義問題的解空間;

(2) 確定易於搜尋的解空間結構;

(3) 以深度優先方式搜尋解空間,並且在搜尋過程中用剪枝函式避免無效搜尋。

我們來看一下遞迴實現回朔法的模板**:

void backtrace(int t) 

}

下邊看幾個leetcode上幾道典型的回朔法:

題目一:

題目的大意就是按照手機鍵盤上,每個數字可以表示的意義,給定乙個字串數字,列舉出所有可能的字元組合~

結題思路:使用遞迴模板搞定

public class solution ;

public listlettercombinations(string digits)

private void generate(string digits,int index,string s)

char c = digits.charat(index);

if(c>='0'&&c<='9'&&c!='1')

// list中儲存了乙個有index個元素的排列

// 向這個排列的末尾新增第index+1個元素,獲得乙個有index+1個元素的排列

private void get1result(int nums,int index,listlist)

for(int i = 0;i

題目三:求所有組合

題目大意就是說從n個數中取出k個數,找出所有的組合,利用遞迴模板**,我們可以得出以下的**:

public class solution

// 求解c(n,k),當前已經找到的組合儲存在c中,需要從start開始搜尋新的元素

private void generatecombine(int n,int k,int start ,listlist)

// 遞迴過程

for(int i = start;i<=n;i++)

}}

執行結果如下:用了25ms。

這個時候就涉及到了一種回溯剪枝的問題,我們還是依照例子中的n = 4, k = 2來說明,有如下的樹形圖:

也就是說,我們可以在遞迴過程中,將不必要的枝條從樹中減掉,比如說本例中的取4!!!

剪枝之後的**如下:

public class solution 

// 求解c(n,k),當前已經找到的組合儲存在c中,需要從start開始搜尋新的元素

private void generatecombine(int n,int k,int start ,listlist)

// 遞迴過程

// 還有k-list.size()個空位,所以,[i...n]中至少要有k-list.size()個元素

// i最多為n-(k-list.size())+1,否則沒有那麼多元素可以放入list中了。

for(int i = start;i<=n-(k-list.size())+1;i++)

}}

執行結果如下:僅僅只用了4ms,也就是說少用了21ms,簡直就是完美的提公升~

總結:

針對遞迴實現的回溯法,我們的基本思路是,首先定義乙個用於遞迴的函式,在主函式中呼叫該遞迴函式;然後在遞迴函式中先判斷是否達到了遞迴結束條件,之後進行迴圈遍歷,在迴圈過程中,依次進行遞迴操作,設計到list的操作,主要要remove進行回退;最後,如果可以的話,記得注意剪枝操作,可以大大提公升執行效率哦~

回朔法 八皇后問題

八皇后問題,是乙個古老而著名的問題,是回溯演算法的典型案例。該問題是國際西洋棋棋手馬克斯 貝瑟爾於1848年提出 在8 8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。假設八個皇后的位置分別用x1到x8表示,那麼xi可以取的值為1 8...

leetcode 78子集(回朔法)

由於leetcode刷過的題,不會儲存,所以將 以及做題時的思路記錄在此,方便日後整理複習思路 class solution def subsets self,nums list int list list int self.result if len nums 0 return self.find...

數字全組合 遞迴法,回朔法

1.遞迴法 void comb int number,int count,int parray else int main 建立動態陣列 parray malloc sizeof int count 1 if parray parray 0 count comb number,count,parra...