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才有可行結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM