解空間樹:是依據待解決問題的特性,用樹結構表示問題的解結構、用葉子表示問題的解的一顆樹。
一、回溯法:采取深度遍歷策略搜索解空間樹,若當前結點不滿足問題的求解要求,則回溯到樹的上一層繼續搜索另一棵子樹,這種解決問題的方法稱為回溯法;
1、用回溯法求解問題,重點是設計問題的解空間樹,解題過程就是搜索解空間樹的過程;
2、構造解空間樹,就是將求解的一系列判斷決策過程及各種可能的結果用樹形結構呈現;
N皇后問題,在給定的N×N的棋盤上放置N個皇后,要求給出各皇后彼此不受攻擊(不在同一行,同一列,同一對角線)的所有可能的棋盤布局。
解題思路,可用一維數組表示N皇后問題的解,queen[i]表示第i行皇后所在的列號;
1 /* c語言代碼 */ 2 #include <stdio.h> 3 /* 八皇后 */ 4 const int N = 8; 5 int queens[N] = {0}; 6 /* 打印 */ 7 void print(int count){ 8 printf("%-3d[",count); 9 for(int i=0; i<N; ++i){ 10 if(i) 11 printf(","); 12 printf("%d",queens[i]); 13 } 14 printf("]\n"); 15 } 16 /* 可以放 */ 17 int can_place(int k, int i){ 18 for(int j=0; j<k; ++j){ 19 if(queens[j] == i || queens[j] - i == j - k|| 20 queens[j] - i == k - j) return 0; 21 } 22 return 1; 23 } 24 /* 放 */ 25 void place(int k){ 26 if(k == N){ 27 static int count = 0; 28 count++; 29 print(count); 30 } 31 else{ 32 for(int i=0; i<N; ++i)// 33 { 34 if(can_place(k,i)) 35 { 36 queens[k] = i; 37 place(k+1); 38 } 39 } 40 } 41 } 42 int main() 43 { 44 place(0); 45 return 0; 46 }
1 #python 代碼 2 N = 8 3 queens = [0] * N 4 count = 0 5 def can_place(k,i): 6 for j in range(k): 7 if queens[j] == i or queens[j]-i == j-k or queens[j]-i == k-j: 8 return False 9 return True 10 11 def place(k): 12 if k == N: 13 global count 14 count = count + 1 15 print(count,queens) 16 else: 17 for i in range(N): 18 if can_place(k,i): 19 queens[k] = i 20 place(k+1) 21 22 place(0)
二、分支界限法,通過遍歷解空間樹來求解問題,通過結點優先級的設計,采用廣度優先,結合優先隊列,的策略遍歷解空間樹,適用於求取問題的最優解或滿足條件的一個解;
分支界限法搜索策略:
1、從根開始,首先生成當前結點所有可能的兒子,並計算兒子結點的優先級,將其放入優先隊列中;
2、從優先隊列中選擇一個優先級最高(最有可能得到最優解)的結點出隊,並作為當前結點繼續生成其各兒子結點、計算優先級且入隊;
3、重復2,直至到達葉子結點,找到滿足要求的一個解,或搜索到最優解;