具體問題如下圖
先看一下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才有可行結