1. 程式人生 > >n皇后問題_回溯法

n皇后問題_回溯法

 具體問題如下圖

先看一下4*4的回溯過程

 

程式結束條件: 一組解:設標誌,找到一解後更改標誌,以標誌做為結束迴圈的條件。 所有解:k=0

判斷約束函式判斷第k個後能不能放在x[k]處 兩個皇后不能放在統一斜線上: 若2個皇后放置的位置分別是(i,j)和(k,l), 且 i-j = k -l 或 i+j = k+l,則說明這2個皇后處於同一斜線上。

下面是利用遞迴和非遞迴實現的程式碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 int x[100];
5 int sum=0; 6 7 /* 8 判斷第k個後能不能放在x[k]處 9 兩個皇后不能放在統一斜線上: 10 若2個皇后放置的位置分別是(i,j)和(k,l), 11 且 i-j = k -l 或 i+j = k+l,則說明這2個皇后處於同一斜線上。 12 */ 13 void output(){ 14 cout << "" <<sum << "种放置方法為:" << endl; 15 for(int i=1;i<=n;i++){ 16 cout << "(" <<i << "
," << x[i] << ")" << endl; 17 } 18 19 } 20 int place(int k){ 21 for(int j=1;j<k;j++){ 22 if(x[j]==x[k] || abs(x[j]-x[k])== abs(j-k)) 23 return 0; 24 } 25 return 1; 26 } 27 void BackTrace(int t,int n){//遞迴 28 if(t>n){////如果t>n說明已經完成一次放置 29 sum++;
30 output(); 31 } 32 else{ 33 for(int i=1;i<=n;i++){ 34 x[t]=i; 35 if(place(t)){// //可以放在i位置處,則繼續搜尋 36 BackTrace(t+1,n); 37 } 38 } 39 40 } 41 } 42 43 void BackTrace1(int n){//非遞迴 44 int k; 45 x[1]=0; 46 k=1; 47 while(k>=1){ 48 x[k]+=1;////先放在第一個位置 49 while((x[k]<=n && !(place(k)))){//如果不能放 50 x[k]++;// //放在下一個位置 51 } 52 if(x[k]<=n){ 53 if(k==n){// //如果已經放完了n個皇后 54 sum++; 55 output(); 56 } 57 else{// //沒有處理完,讓k自加,處理下一個皇后 58 k++; 59 x[k]=0; 60 } 61 }else{// 當前無法完成放置,則進行剪枝,回溯回去,回到第k-1步 62 k--; 63 } 64 } 65 } 66 int main() 67 { 68 memset(x,0,sizeof(x)); 69 cin >> n; 70 cout << n << "皇后的放置方法為" << endl; 71 //BackTrace(1,n); 72 BackTrace1(n); 73 return 0; 74 }

 

執行結果如下

 

 皇后個數要大於3才有可行結