暴力搜尋 回溯法

2021-06-29 02:02:05 字數 1526 閱讀 5207

回溯法(backtracking)是深度優先搜尋(dfs)的一種,按照深度優先的順序便利解答樹。應用範圍很廣,只要能把待求解的問題分成不太多的步驟,每個步驟又只有不太多的選擇,都可以考慮應用回溯法。在學習回溯法之前,一定要保證遞迴程式能熟練準確地寫出。

當把問題分成若干步驟並遞迴求解時,如果當前步驟沒有合法選擇則函式將返回上一級遞迴呼叫。

例如:八皇后問題:在棋盤上放置八個皇后,使得它們互不攻擊,每個皇后的攻擊範圍是同行同列同對角線,找出所有解的個數。

如果把問題相成從64個格仔中選8個格仔,那麼根據組合數學需要4.426*10^9種方案,但是如果用陣列c[x]表示第x行皇后的列編號,則問題變成了全排列生成問題。而0~7的全排列一共有8!=40320個,列舉量不會超過它 。

下面以四皇后問題闡述具體思路:

第一行,皇后可以在第一列、第二列、第三列、第四列。用a[i][j]來表示皇后可能放置的位置,如圖

假設第一行的皇后在a[0][0],那麼在第二行皇后可能放置的合法位置如圖

假設第二行皇后放在a[1][2],那麼第三行無法放皇后,所以回溯到第一行的a[0][0],走下一條路a[1][3],如圖

第四行無法再放置皇后,說明第乙個皇后不能在a[0][0],回溯到最開始,讓皇后放置在a[0][1],依此類推得到解答樹。

觀察解答樹,改變一次行,遍歷四個列(a[1][0]和a[1][1]的情況由於不放置皇后所以沒有畫在圖上,但是這兩種情況的否定需要遍歷判斷),所以只需要用乙個一維陣列c[x]來表示第x行皇后的列編號即可。**如下:

需要在主函式中讀入n(n*n的棋盤),並將解的個數tot清零,然後呼叫dfs(0),即可求得解。

void dfs(int cur)                                //cur表示行 

} if(ok)

dfs(cur + 1);

} }}

c[cur] == c[j] 、cur - c[cur] == j - c[j]、cur + c[cur] == j + c[j]的理解如下:

由於是逐行放置,所以橫向一定不會衝突,只需檢查是否縱向和斜向衝突即可,在直角座標系中,y = -x與y = x為正斜向線,模擬座標系,cur為行,抽象為橫座標,c[cur]為列,抽象為縱座標,由於不一定要通過原點,所以y-x與y+x可以為任意常數,只要這個常數與前一行相等,說明兩皇后斜向衝突。

2021 3 1 79 單詞搜尋 回溯法)

題目 給定乙個二維網格和乙個單詞,找出該單詞是否存在於網格中。單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中 相鄰 單元格是那些水平相鄰或垂直相鄰的單元格。同乙個單元格內的字母不允許被重複使用。示例 board a b c e s f c s a d e e 給定 word abcced ...

回溯法遵循深度優先嗎 深度優先搜尋(回溯法)

事實上,深度優先搜尋屬於圖演算法的一種,英文縮寫為dfs即depth first search.其過程簡要來說是對每乙個可能的分支路徑深入到不能再深入為止,而且每個節點只能訪問一次.舉例說明之 下圖是乙個無向圖,如果我們從a點發起深度優先搜尋 以下的訪問次序並不是唯一的,第二個點既可以是b也可以是c...

poj 1935 搜尋 回溯

解題思路 先我們考慮從源點出發到所有自己想要經過的點然後在回到源點sum,顯然每條邊都必須經過源點 這個我們可以一次dfs求出 但題目的意思是可以不用回到源點,那麼我們可以再求源點到所有要經過的點的最遠距離ans,於是答案便是sum ans.這道題的思路確實是很巧妙,一開始我還是在想如何表示從某一點...