一、問題
在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 搜尋解空間 約束...