舉個例子來看:請對"ABCD"這四個字進行排列,我們知道有24(4!)種答案,如果是一般遞迴的算法,一一枚舉所有可能的答案,就會產生AAAA,AAAB,...AADD這種不符合的答案,而且總共產生了64(4^4)種結果,比24大了不少。先來看底下這段程式碼示範如何用Backtracking排列這4個字:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
using namespace std; | |
string str; | |
string Ans; // 過程中保存答案用 | |
bool choosed[100] = {0}; // choosed[i]==1表示編號i已經出現過 | |
void backtracking(const int &N); | |
int main() | |
{ | |
str = "ABCD"; | |
backtracking(4); | |
} | |
void backtracking(const int &N) // N表示有N個字 | |
{ | |
if (Ans.size() == N) { // 終止條件檢查 | |
cout << Ans << endl; | |
return; | |
} | |
for (int i = 0; i < N; ++i) { | |
if (choosed[i] == 0){ // 如果這個編號還沒出現過(可行性檢查) | |
Ans.push_back(str[i]); // 則將它放入Ans | |
choosed[i] = 1; // 並且讓choosed[i]變成1,避免下個遞迴選到 | |
backtracking(N); // 進入下一層遞迴 | |
Ans.pop_back(); // 將編號i這個字從Ans移除 | |
choosed[i] = 0; // 並標示成未選過 | |
} | |
} | |
} |

可以發現Backtracking演算法在每次遞迴前都會先檢查答案的可行性,必須確認"到目前為止都是正確"的才會繼續往下遞迴,因此就能避免產生錯誤的答案,以上面的例子來看就少了40個錯誤了答案。
Backtracking整體的架構如下:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void backtracking (int N, int Len) | |
{ | |
if (Len == N) { | |
輸出答案; | |
return; | |
} | |
for (可能的數字) { | |
if (這數字符合) | |
backtracking(N, Len + 1); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void backtracking() | |
{ | |
if (填完所有空格) { | |
輸出解答; | |
return; | |
} | |
for (int i = 1; i <= 9; ++i) { | |
if (i符合規則) { | |
將i填入空格; | |
backtracking(); // 遞迴下去填下個空格 | |
將i從空格移除; | |
} | |
} | |
} |
沒有留言:
張貼留言