日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

算法设计与分析——回溯法——n皇后问题

發(fā)布時(shí)間:2023/12/4 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法设计与分析——回溯法——n皇后问题 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、什么是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。因此有:

由此約束條件剪去不滿足行、列和斜線約束的子樹。程序的遞歸回溯實(shí)現(xiàn)如下:

遞歸回溯

#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;}


迭代回溯:

#include<iostream> using namespace std; class Queen{public:bool Place(int k);void Backtrack(int t);int n;//皇后的個(gè)數(shù) int *x;//當(dāng)前的解 ,也表示當(dāng)前的列。因?yàn)榱芯褪堑捻樞蚓褪亲罱K的解 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) {//k表示當(dāng)前的行,x[k]表示當(dāng)前的列 x[1]=0;//初始化第一行,0表示所有位置均沒(méi)有放"后";int k=1;//初始化第一行 while(k>0){x[k]+=1;//移動(dòng)到下一列 while((x[k]<=n)&&!(Place(k)))//在第k行找到一個(gè)可以放后的位置 {x[k]+=1; }if(x[k]<=n)//如果找到可以放后的位置 {if(k == n)//如果當(dāng)前行是最后一行,找到可行解 {sum++;for(int i=1;i<=n;i++){cout<<x[i];}cout<<endl;}else//如果當(dāng)前解不是最后一行,找到可行解 {k++;x[k]=0;}}elsek--;//如果第k行沒(méi)有找到可以放后的位置,此時(shí)行號(hào)減一//返回到第k-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皇后的問(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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。