算法设计与分析——回溯法——n皇后问题
一、什么是N皇后問題?
在n×n格的棋盤上放置彼此不受攻擊的n個皇后。按照國際象棋的規則,皇后可以攻擊與之處在同一行或同一列或同一斜線上的棋子。n后問題等價于再n×n的棋盤上放置n個皇后,任何2個皇后不妨在同一行或同一列或同一斜線上。
問題解析:用n元數組x[1:n]表示n后問題的解。其中,x[i]表示皇后i放在棋盤的第i行的第x[i]列。由于不允許將2個皇后放在同一列上,所以解向量中的x[i]互不相同。如果將n*n的棋盤看做是二維方陣,其行號從上到下,列號從左到右依次編號為1,2,……n。設兩個皇后的坐標分別為(i,j)和(k,l)。若兩個皇后在同一斜線上,那么這兩個皇后的坐標連成的線為1或者-1。因此有:
遞歸回溯
#include<iostream> using namespace std; class Queen{public:bool Place(int k);void Backtrack(int t);int n;//皇后的個數 int *x;//當前的解 long sum;//當前已找到的可行方案數 };bool Queen::Place(int k)//剪枝函數 {for(int j=1;j<k;j++){if((abs(k-j) == abs(x[k]-x[j]))||(x[k] == x[j]))//同一對角線上,同一列上的不符合條件 return false;}return true;} void Queen::Backtrack(int t) {if(t>n)//如果到達了葉子結點,則說明這是一個解 {sum++;for(int i=1;i<=n;i++){cout<<x[i]; } cout<<endl;}else{for(int i=1;i<=n;i++)// 遍歷這一行的每一個位置 {x[t]=i;//先假設,這一行進入的是第i個 if(Place(t))//判斷一下這個點是否滿足n皇后問題的要求 Backtrack(t+1);//如果滿足了則進入下一步 }}} int nQueen(int n) {Queen X;//初始化X;X.n=n;X.sum=0;int *p = new int [n+1];for(int i=0;i<=n;i++){p[i]=0;}X.x = p;X.Backtrack(1);delete[]p;return X.sum; } int main() {int n;cout<<"輸入n皇后的問題中皇后的個數n:";cin>>n; cout<<n<<"皇后的問題解共"<<endl;cout<<nQueen(n)<<"個解"<<endl;}
迭代回溯:
五、N皇后問題解的個數
n solution(n)
1 1
2 0
3 0
4 2
5 10
6 4
7 40
8 92
9 352
10 724
11 2680
12 14200
13 73712
14 365596
15 2279184
16 14772512
17 95815104
18 666090624
19 4968057848
20 39029188884
21 314666222712
22 2691008701644
23 24233937684440
24 227514171973736
25 2207893435808352
總結
以上是生活随笔為你收集整理的算法设计与分析——回溯法——n皇后问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新 Linux 驱动补丁提交:RISC-
- 下一篇: 算法设计与分析——回溯法——符号三角形问