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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/4 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法设计与分析——回溯法——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;}


迭代回溯:

#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) {//k表示當前的行,x[k]表示當前的列 x[1]=0;//初始化第一行,0表示所有位置均沒有放"后";int k=1;//初始化第一行 while(k>0){x[k]+=1;//移動到下一列 while((x[k]<=n)&&!(Place(k)))//在第k行找到一個可以放后的位置 {x[k]+=1; }if(x[k]<=n)//如果找到可以放后的位置 {if(k == n)//如果當前行是最后一行,找到可行解 {sum++;for(int i=1;i<=n;i++){cout<<x[i];}cout<<endl;}else//如果當前解不是最后一行,找到可行解 {k++;x[k]=0;}}elsek--;//如果第k行沒有找到可以放后的位置,此時行號減一//返回到第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皇后的問題中皇后的個數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皇后问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。