回溯法的基本行為是搜尋,搜尋過程使用剪枝函式來為了避免無效的搜尋。剪枝函式包括兩類:1. 使用約束函式,剪去不滿足約束條件的路徑;2.使用限界函式,剪去不能得到最優解的路徑。
(1)針對所給問題,確定問題的解空間:
首先應明確定義問題的解空間,問題的解空間應至少包含問題的乙個(最優)解。
(2)確定結點的擴充套件搜尋規則
(3)以深度優先方式搜尋解空間,並在搜尋過程中用剪枝函式避免無效搜尋。
(1)問題框架
設問題的解是乙個n維向量(a1,a2,………,an),約束條件是ai(i=1,2,3,…..,n)之間滿足某種條件,記為f(ai)。
(2)非遞迴回溯框架
1:int a[n],i;
2: 初始化陣列a;
3: i = 1;
4:while (i>0(有路可走) and (未達到目標)) // 還未回溯到頭
5:
10:else
// 處理第i個元素
11:
17:if(a[i]在搜尋空間內)
18:
22:else
23:
27: }(3)遞迴的演算法框架
回溯法是對解空間的深度優先搜尋,在一般情況下使用遞迴函式來實現回溯法比較簡單,其中i為搜尋的深度,框架如下:
int a[n];
2:traceback(int i)
3:
17: }
18: }
19: }(1)問題描述: n皇后問題是乙個經典的問題,在乙個n*n的棋盤上放置n個皇后,每行乙個並使其不能互相攻擊(同一行、同一列、同一斜線上的皇后都會自動攻擊)。
(2)問題分析:對於n皇后問題來說,其核心就是乙個回溯問題,假設每個皇后都放在棋盤上的不同的行,則把這個條件就當成乙個顯示約束條件,後面則不用加以考慮位於不同行的問題,所以該問題的約束條件就簡化成了兩個皇后不能位於同一列和同一斜線,對於不位於同一列來說即兩個皇后的縱座標不想等即可滿足這一條件,不位於同一斜線則兩個皇后的連線的斜率不為1則滿足該條件。
(3)問題例項:
如圖所示是乙個經典的四皇后求解問題
a.首先將第乙個皇后放置於(1,1)。如圖(a)
b.則對於第二個皇后來說,由於其不能與第乙個皇后同列則不能放在(2,1)位置,又由於其不能與第乙個皇后放在同一斜線上,則不能放在(2,2)位置(當位於(2,2)位置時,其與第乙個皇后連線的斜率為1),則其可以放在(2,3)。(2,4),首先將其放在(2,3)
c對於第三個皇后來說,由於不能與第1,2個皇后同列,則不能在(3,1),(3,3),而又不能與第2個皇后同一斜線,則不能位於(3,2),(3,4)。則第3個皇后無處可放,則回溯到上一步,再次尋求合適的解。
d.即回溯到第2個皇后的位置,說明其放置在(2,3)無解,則放置到(2,4)這個位置,再依次考慮3,4皇后的位置問題。
e.....................
f.走完一次,可得到乙個解為(1,1)(2,4)(3,1)(4,3)。
(4)c**實現:
#include
#include
int n;
int x[50]=;
int sum=0;
/**判斷可不可以放置,
位於同一列
同一對角線則不能放置
**/
int place(int k)
return 1;
}void print()
void traceback(int t)
else
for(i=1;i<=n;i++)
}void backtrack()
else
}else
k--;}}
int main()
reference:
回溯法解決N皇后問題
在棋盤上放置8個皇后,使得它們互不攻擊,此時每個皇后的攻擊範圍為同行同列和同對角線,要求找出所有解。遞迴函式將不再遞迴呼叫它自身,而是返回上一層呼叫,這種現象稱為回溯 backtracking 當把問題分成若干步驟並遞迴求解時,如果當前步驟沒有合法選擇,則函式將返回上一級遞迴呼叫,這種現象稱為回溯。...
回溯法解決N皇后的問題
使用回溯法解決n皇后的問題 def mk lst size 生成棋盤 return 0 for i in range size for j in range size def is legal posi loca,size 判斷是否合法座標 x,y loca 0 loca 1 size 1 if 0...
N 皇后問題 回溯法
n 皇后問題 在 n n 的棋盤上放置彼此不受攻擊的 n 個皇后,任意兩個皇后不同行 不同列 不同斜線。思路 1.因為皇后不能同行,所以,在每一行放置乙個皇后就行 2.當在一行放置皇后的時候 1 順序檢查這一行每乙個位置是否和上面所有的皇后,只要有乙個同列或者在斜線上就不能放置 若找到乙個滿足的,放...