回溯法:有通用解題法 之稱,能夠系統的搜索一個問題的全部解和任一解,是一個既帶有系統性,又帶有跳躍性的搜索算法。算法
算法基本思想:函數
肯定解空間後spa
從開始節點出發,以深度優先的方式搜索整個解空間。code
若是當前擴展結點不能再向縱深方向移動,當前節點爲死節點。此時,應該往回移動至最近的一個活節點處。,並是這個或節點成爲當前節點的擴展結點。blog
提升算法方式(剪枝函數):遞歸
1 用約束函數在擴展結點出剪去不知足約束的子樹class
2 用限界函數剪去得不到最優解的子樹。擴展
回溯法解題步驟:搜索
1 定義問題的解空間集合
2 肯定易於搜索的解空間結構
3 以深度優先方式搜索解空間,並在搜索過程當中用剪枝函數避免無效搜索。
遞歸回溯:
void Backtrack(int t) { if(t>n) Output(x); else for(int i=f(n,t);i<=(g,t);i++) { x[t] = h(i); if(Constraint(t) && Bound(t)) Backtrack(t+1); } }
子集樹:
當全部的問題是從n個元素的集合S中找出知足某種性質的子集時,相應的解空間樹稱爲子集樹。
僞碼爲:
void Backtrack(int t) { if(t>n) Output(x); else for(int i=f(n,t);i<=(g,t);i++) { x[t] = h(i); if(Constraint(t) && Bound(t)) Backtrack(t+1); } }
排列樹:
當所給的問題是肯定n個元素知足某種性質的排列時,相應的解空間樹稱爲排列數。
僞碼爲:
void Backtrack(int t) { if(t>n) Output(x); else for(int i=f(n,t);i<=(g,t);i++) { Swap(x[t],x[i]); if(Constraint(t) && Bound(t)) { Backtrack(t+1); } Swap(x[t],x[i]); } }