回溯法的總結
阿新 • • 發佈:2020-12-12
回溯法的總結
回溯法的解空間樹主要包含\(n\)叉樹、排列樹、子集樹。
例如在回溯法求解\(N\)皇后問題時,採用\(n\)叉樹的結構,如下圖所示:
該解空間即為\(n\)叉樹的情況,當\(x_1\)選擇\(1\)時,即進入第一個分支,進而在通過剪枝函式判斷,當前分支是否有可能為最優解,若為可能產生最優解則展開第一個分支;若不可能,則剪去該分支。依次遞迴下去對\(x_2, x_3, ...\)分別求解,當到達最後樹的葉子結點,即表示這種情況可行,就可以進行後續操作,包括儲存路徑或儲存最優解等。
當一條分支執行完畢後,退出當前遞迴,即返回上一層的狀況,這就需要我們將進入分支時,對資料的修改撤回,體現在BackTrack1(t + 1);
最大團問題求解時,該特點明顯,如下:
void BackTrack(int i) { if (i > n) { for (int j = 1; j <= n; j++) bestx[j] = x[j]; bestn = cn; return ; } int ok = 1; for (int j = 1; j < i; j++) if (x[j] == 1 && a[i][j] == 0) { ok = 0; break; } if (ok) { x[i] = 1; cn++; BackTrack(i + 1); cn--; } if (cn + n - i > bestn) { x[i] = 0; BackTrack(i + 1); } }
可以發現在\(17\)行中BackTrack(i + 1);
的前後程式碼是對稱的,cn++
在退出遞迴時,進行了cn--
撤銷了對cn的操作。而x[i] = 1;
由於每次遞迴時都需要重新賦值,因此無需寫出其對稱程式碼。
9~13
行即為剪枝函式,將結點與已成團的結點不相連的分支直接剪去,不進行遞迴訪問,提高搜尋效率。20~23
為限界函式,要求右子樹中,剩下的所有結點數和以及抱團的結點數大於當前最優解數,這樣才有可能有更好的解,進行遞迴訪問,
總得來說,回溯法主要是遍歷問題的所有可行解,將所有的解構成樹的解空間,在通過剪枝函式和限界函式,剪去錯誤的分支,降低無效的搜尋,以此提高搜尋效率。