算法设计与分析——回溯法——n皇后问题
一、什么是N皇后問(wèn)題?
在n×n格的棋盤上放置彼此不受攻擊的n個(gè)皇后。按照國(guó)際象棋的規(guī)則,皇后可以攻擊與之處在同一行或同一列或同一斜線上的棋子。n后問(wèn)題等價(jià)于再n×n的棋盤上放置n個(gè)皇后,任何2個(gè)皇后不妨在同一行或同一列或同一斜線上。
問(wèn)題解析:用n元數(shù)組x[1:n]表示n后問(wèn)題的解。其中,x[i]表示皇后i放在棋盤的第i行的第x[i]列。由于不允許將2個(gè)皇后放在同一列上,所以解向量中的x[i]互不相同。如果將n*n的棋盤看做是二維方陣,其行號(hào)從上到下,列號(hào)從左到右依次編號(hào)為1,2,……n。設(shè)兩個(gè)皇后的坐標(biāo)分別為(i,j)和(k,l)。若兩個(gè)皇后在同一斜線上,那么這兩個(gè)皇后的坐標(biāo)連成的線為1或者-1。因此有:
遞歸回溯
#include<iostream> using namespace std; class Queen{public:bool Place(int k);void Backtrack(int t);int n;//皇后的個(gè)數(shù) int *x;//當(dāng)前的解 long sum;//當(dāng)前已找到的可行方案數(shù) };bool Queen::Place(int k)//剪枝函數(shù) {for(int j=1;j<k;j++){if((abs(k-j) == abs(x[k]-x[j]))||(x[k] == x[j]))//同一對(duì)角線上,同一列上的不符合條件 return false;}return true;} void Queen::Backtrack(int t) {if(t>n)//如果到達(dá)了葉子結(jié)點(diǎn),則說(shuō)明這是一個(gè)解 {sum++;for(int i=1;i<=n;i++){cout<<x[i]; } cout<<endl;}else{for(int i=1;i<=n;i++)// 遍歷這一行的每一個(gè)位置 {x[t]=i;//先假設(shè),這一行進(jìn)入的是第i個(gè) if(Place(t))//判斷一下這個(gè)點(diǎn)是否滿足n皇后問(wèn)題的要求 Backtrack(t+1);//如果滿足了則進(jìn)入下一步 }}} 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皇后的問(wèn)題中皇后的個(gè)數(shù)n:";cin>>n; cout<<n<<"皇后的問(wèn)題解共"<<endl;cout<<nQueen(n)<<"個(gè)解"<<endl;}
迭代回溯:
五、N皇后問(wèn)題解的個(gè)數(shù)
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
總結(jié)
以上是生活随笔為你收集整理的算法设计与分析——回溯法——n皇后问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 新 Linux 驱动补丁提交:RISC-
- 下一篇: 算法设计与分析——回溯法——符号三角形问