但中間也在用零碎的時間學學別的,今天寫總結一下回溯法。
在最壞的情況下,回溯法會導致一次複雜度為指數時間的計算。
回溯法實際上是一種 dfs(深度優先搜尋演算法)的一種,不同的是,回溯法具備剪枝的能力,下面通過兩個例子來具體分析回溯演算法。
n 皇后問題是基於八皇后問題的進一步發展,如何能夠在 n * n 大小的西洋棋棋盤上擺放 n 個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行、縱行或斜線上。下圖為八皇后問題的其中乙個解。
下面來分析下這個問題。
棋盤上每個位置包含兩種狀態:有皇后以及沒有皇后。在不考慮約束條件的情況下,列出所有組合,我們將得到乙個深度為 n * n 的二叉樹。
上圖描述了棋盤前兩個位置的可能性。
最簡單的辦法是窮舉出所有可能性,然後篩選出符合的解。可以通過 dfs 演算法遍歷這個二叉樹,對於 n * n 的棋盤將有 2 的 n * n 次方種可能,這顯然是不可接受的。
但我們可以通過規則來進行剪枝,可以使用的規則如下:
通過上述四個條件,我們可以減掉大部分的路徑。
現在回到回溯法上來看這道題,回溯法使用試錯的思想,分步解決問題,我們可以先假設第乙個位置放置皇后,然後根據規則,找到第二個合法的位置再放置第二個皇后,如果找不到合適的位置則表示該路徑錯誤,回溯到上乙個位置繼續。
回溯法特徵之一就是會使用陣列或其他資料結構儲存遍歷資訊,從而跳過不合法的路徑。
本題使用三個陣列分別儲存列、左上至右下斜邊、右上至坐下斜邊的皇后擺放資料。
因為每行只能擺放乙個皇后,所以我們按行遍歷,嘗試在當前行每乙個位置放置皇后。然後跳到下一行繼續。
下面直接放上**:
public list
>
solvenqueens
(int n)
private
void
backtrace
(int n,
int row,
boolean
column,
boolean
rl,boolean
lr,int[
] board, list
> result)
boardlist.
add(rowbuilder.
tostring()
);} result.
add(boardlist);}
//for
(int columnindex =
0; columnindex < n; columnindex++)}
}
數獨遊戲就是我們常見的那個解數獨的遊戲。
思路跟 n 皇后一樣,遍歷所有空格,逐個將 1-9 陣列放置空格內,通過規則判斷是否合法,最終找到解。
這裡同樣需要定義三個陣列用於存放遍歷資料:每行、每列、每 3x3 宮格內的資料。
另外,如果 sn 表示 第 n 個 3x3 宮格,那麼 sn = (row / 3) * 3 + column / 3;
public
void
solvesudoku
(char
board)
if(columnrecord[column]
== null)
int boxindex =
(row /3)
*3+ column /3;
if(boxrecord[boxindex]
== null)
if(c !=
'.')}}
backtrack
(board,0,
0, rowrecord, columnrecord, boxrecord);}
private
boolean
backtrack
(char
board,
int row,
int column,
list
rowrecord,
list
columnrecord,
list
boxrecord)
int nextrow = column <
8? row : row +1;
int nextcolumn = column <
8? column +1:
0;int boxindex =
(row /3)
*3+ column /3;
character currentchar = board[row]
[column];if
(currentchar ==
'.')
else}}
}else
return
false
;}
上面的**我放在 github 上了,裡面還有很多其他資料結構與演算法相關的**,需要的可以看看: 回溯法解數獨
前天在我的小pad上裝了個數獨遊戲,完了幾把後興趣索然了。不過突然想起來一直想寫個解數獨的程式,不過因為懶和拖拉,就一直沒寫。今天花了30分鐘寫了個解數獨的程式,貼 include include include 某個數字填入後,需要檢查的index void get affected index ...
leetcode 解數獨 回溯法
如 方法 回溯法 回溯法的思想就是 對於乙個問題有多個選擇方式,先選擇乙個方式執行下去,若在執行過程中,發現不符合規則,則回退,回到選擇方式的步驟,進而選擇其他方式,繼續試。重要 對於回溯法,一定會有個 規則 這個 規則 將會決定是否回退,所以當我們在使用回溯法時,一定要留意能否構建 規則 如這一題...
N 皇后問題 回溯法
n 皇后問題 在 n n 的棋盤上放置彼此不受攻擊的 n 個皇后,任意兩個皇后不同行 不同列 不同斜線。思路 1.因為皇后不能同行,所以,在每一行放置乙個皇后就行 2.當在一行放置皇后的時候 1 順序檢查這一行每乙個位置是否和上面所有的皇后,只要有乙個同列或者在斜線上就不能放置 若找到乙個滿足的,放...