回溯法,又稱為試探法,按選優條件向前不斷搜尋,以達到目標。但是當探索到某一步時,如果發現原先選擇並不優或達不到目標,就會退回一步重新選擇,這種達不到目的就退回再走的演算法稱為回溯法。
與窮舉法的區別和聯絡:對於可以使用回溯法來解決的問題,首先可以將其解空間可以看成一棵解空間樹。在回溯法中,每次擴大當前部分解時,都面臨乙個可選的狀態集合(所有的子樹),每個樹結點代表乙個可能的部分解。相同點:它們都是基於試探的。
區別:窮舉法要將乙個解的各個部分全部生成後,才檢查是否滿足條件,若不滿足,則直接放棄該完整解,然後再嘗試另乙個可能的完整解,它並沒有沿著乙個可能的完整解的各個部分逐步回退生成解的過程。而對於回溯法,乙個解的各個部分是逐步生成的,當發現當前生成的某部分不滿足約束條件時,就放棄該步所做的工作,退到上一步進行新的嘗試,而不是放棄整個解重來。
回溯法對任一解的生成,一般都採用逐步擴大解的方式。每前進一步,都試圖在當前部分解的基礎上擴大該部分解。它在問題的狀態空間樹中,從開始結點(根結點)出發,以深度優先搜尋整個狀態空間。這個開始結點成為活結點,同時也成為當前的擴充套件結點。在當前擴充套件結點處,搜尋向縱深方向移至乙個新結點。這個新結點成為新的活結點,並成為當前擴充套件結點。如果在當前擴充套件結點處不能再向縱深方向移動,則當前擴充套件結點就成為死結點。此時,應往回移動(回溯)至最近的活結點處,並使這個活結點成為當前擴充套件結點。回溯法以這種工作方式遞迴地在狀態空間中搜尋,直到找到所要求的解或解空間中已無活結點時為止。
針對給定的問題,定義問題的解空間;
確定易於搜尋的解空間結構;
以深度優先方式搜尋解空間,並且在搜尋過程中用剪枝函式避免無效搜尋。(這裡的剪枝函式就是判斷該結點是否滿足問題題設,如果滿足則向下搜尋,不滿足則在此剪枝)
1. 遞迴實現:
變數解釋:
x:儲存試探解的陣列
n:解空間樹的層數
i:搜尋目前所達到的層數
start:子節點解空間的最小值
end:子節點解空間的最大值
int x[n];
void backtrack (int i) else else }}
}
2. 非遞迴實現:
變數解釋:
x:儲存試探解的陣列
n:解空間樹的層數
i:搜尋目前所達到的層數
start:子節點解空間的最小值
end:子節點解空間的最大值
void f_backtrack(int i)
while (i >= 1) else
// 不滿足條件,在此剪枝(即回溯)
} else
}//遍歷完子節點解空間後,向上剪枝(即回溯)
x[i] = 1;
i--;
x[i]++;
}}
相比之下,遞迴設計方法比較簡單,而非遞迴方法,也就是迴圈方法設計細節比較多,但如果掌握了其特點,對不同問題的適用性很強(即**只需要很少的修改就可以應用到不同問題),加之其最大的優勢:效率更高(因為遞迴的實現是通過呼叫函式本身,函式呼叫的時候,每次呼叫時要做位址儲存,引數傳遞等,這是通過乙個遞迴工作棧實現的。具體是每次呼叫函式本身要儲存的內容包括:區域性變數、形參、呼叫函式位址、返回值。那麼,如果遞迴呼叫n次,就要分配n區域性變數、n形參、n呼叫函式位址、n返回值。這勢必是影響效率的。)
經典問題:八皇后問題遞迴實現為以下**中backtrack方法八皇后問題,是乙個古老而著名的問題,是回溯演算法的典型例題。該問題是十九世紀著名的數學家高斯2023年提出:
在8x8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上(斜率為1),問有多少種擺法。高斯認為有76種方案。2023年在柏林的象棋雜誌上不同的作者發表了40種不同的解,後來有人用圖論的方法解出92種結果。
非遞迴實現為以下**中f_backtrack方法:
#include using namespace std;
int n;
int *x;
int sum;
bool place(int k)
void output()
cout << endl;
}void f_backtrack(int i)
while (i >= 1)
//得到最終可行解,退出
else
}else
}x[i] = 1;
i--;
x[i]++; //回溯
}}void backtrack(int i)
else
else}}}
int main()
五大經典演算法
據說有人歸納了計算機的五大常用演算法,它們是貪婪演算法,動態規劃演算法,分治演算法,回溯演算法以及分支限界演算法。雖然不知道為何要將這五個演算法歸為最常用的演算法,但是毫無疑問,這五個演算法是有很多應用場景的,最優化問題大多可以利用這些演算法解決。演算法的本質就是解決問題。當資料量比較小時,其實根本...
演算法 五大經典搜尋演算法
最簡單的從頭開始對比查詢。int binarysearch int arr,int x,int len if x arr mid else return 1 時間複雜度為o 1 二叉樹的前序遍歷 中序遍歷 後序遍歷測試 如下 package com.tree public class tree sy...
五大常用演算法 回溯法
於 回溯演算法實際上乙個類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就 回溯 返回,嘗試別的路徑。回溯法是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯...