回溯法之n皇后問題

2021-08-21 21:32:15 字數 2817 閱讀 5998

一、問題

在nxn格的棋盤上放置彼此不受攻擊的n格皇后。按照西洋棋的規則,皇后可以攻擊與之處在同一行或同一列或同一斜線上的棋子。n後問題等價於在nxn格的棋盤上放置n個皇后,任何2個皇后不放在同一行或同一列或同一斜線上。

二、演算法與分析

用陣列x[i](1≤i≤n)表示n後問題的解。其中x[i]表示皇后i放在棋盤的第i行的第x[i]列。由於不允許將2個皇后放在同一列,所以解向量中的x[i]互不相同。2個皇后不能放在同一斜線上是問題的隱約束。對於一般的n後問題,這一隱約束條件可以化成顯約束形式。設2個皇后放置位置為(i,j),(k,l):

顯然,棋盤的每一行上可以而且必須擺放乙個皇后,所以,n皇后問題的可能解用乙個n元向量x=(x1, x2, …, xn)表示,其中,1≤i≤n並且1≤xi≤n,即第i個皇后放在第i行第xi列上

由於兩個皇后不能位於同一列上,所以,解向量x必須滿足約束條件:

xi≠xj                                   (式1)

若兩個皇后擺放的位置分別是(i, xi)和(j, xj),在棋盤上斜率為-1的斜線上,滿足條件i-j= xi-xj,在棋盤上斜率為1的斜線上,滿足條件i+j= xi+xj,綜合兩種情況,由於兩個皇后不能位於同一斜線上,所以,解向量x必須滿足約束條件:

|i-xi|≠|j-xj|                                  (式2)

為了簡化問題,下面討論四皇后問題。

四皇后問題的解空間樹是乙個完全4叉樹,樹的根結點表示搜尋的初始狀態,對應backtrack(1,x);從根結點到第2層結點對應皇后1在棋盤中第1行的可能擺放位置,從第2層結點到第3層結點對應皇后2在棋盤中第2行的可能擺放位置,依此類推。

完全4叉樹,我只畫了一部分,完整的應該是除了葉結點,每個內部結點都有四個子結點,k表示層數:

剪枝之後:

回溯法求解4皇后問題的搜尋過程:

當然這個圖只表示到找到的第乙個解,我們知道還有另外乙個解。

三、c++**

變數sum記錄可行方案個數,初始為1;

n表示皇后個數,由使用者輸入;

x陣列儲存問題的解,表示皇后i放在棋盤的第i行第x[i]列,初始時各元素都為0,而我們目的是求出有多少組(x[1],x[2],x[3]......x[n])滿足擺放條件;

output(int x)函式作用是輸出當前找到的乙個可行解,只在搜尋到葉節點時才會呼叫;

place(int k,int x)函式作用是,對當前行k以上的所有行(即1到k-1行)逐行進行檢查,如果該行與上面任何一行相互攻擊(即位於同一對角線上了或同列了:abs(i-k)==abs(x[i]-x[k]) || x[i]==x[k]),那麼返回false,否則返回true;

backtrack(int k,int  x)函式表示搜尋解空間中第k層子樹,k>n時,演算法搜尋至葉節點,得到乙個新的n皇后互不攻擊放置方案,那麼輸出該方案,可行方案數sum加1;k<=n時,當前擴充套件節點是解空間的內部節點,該節點有x[1],x[2],x[3]......x[n]共n個子節點,對每乙個子節點,用函式place檢查其可行性,如果可行,以深度優先的方式遞迴地對可行子樹搜尋,如果不可行剪枝。

#include #include using namespace std;

int sum=0;

int n;

int output(int x)

cout << endl;

return 0;

}bool place(int k,int x)

else

}}int main()

backtrack(1,x);

cout << endl;

cout << "解的個數:" << sum << endl;

system("pause");

return 0;

}

以上的程式易於理解,但如果表示成非遞迴方式,可進一步省去o(n)遞迴棧空間,使用非遞迴的迭代回溯法:

#include #include using namespace std;

int sum=0;

int n;

int output(int x)

cout << endl;

return 0;

}bool place(int k,int x)else

}else

}}int main()

backtrack(1,x);

cout << endl;

cout << "解的個數:" << sum << endl;

system("pause");

return 0;

}

執行結果:

再測試下程式,n輸入其他值:

n=8有92種,n=12有14200種。

N皇后問題之回溯法

time limit 1000msmemory limit 32768kb64bit io format i64d i64u description 在n n的方格棋盤放置了n個皇后,使得它們不相互攻擊 即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。你的任務是,對於...

N 皇后問題 回溯法

n 皇后問題 在 n n 的棋盤上放置彼此不受攻擊的 n 個皇后,任意兩個皇后不同行 不同列 不同斜線。思路 1.因為皇后不能同行,所以,在每一行放置乙個皇后就行 2.當在一行放置皇后的時候 1 順序檢查這一行每乙個位置是否和上面所有的皇后,只要有乙個同列或者在斜線上就不能放置 若找到乙個滿足的,放...

回溯法 n皇后問題

問題描述 在nxn的棋盤上,放置彼此不受攻擊的n個皇后。規則 皇后可以攻擊與之在同一行,同一列,同一斜線上的棋子。以行為主導 不用再判斷是否同行了 演算法設計 1 定義問題的解空間 問題解的形式為n元組 分量xi表示第i個皇后放置在第i行,第xi列。2 解空間的組織結構 m叉樹 3 搜尋解空間 約束...