The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q'
and '.'
both indicate a queen and an empty space respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[ [".Q..", // Solution 1 "...Q", "Q...", "..Q."], ["..Q.", // Solution 2 "Q...", "...Q", ".Q.."] ]
解題思路:
使用回溯法解決N皇后問題,是常見的解決方法。分N步放置皇后,由於皇后之間不能同行、同列、同斜線,所以每次放置皇后的時候,都要考慮是否與已有的皇后“沖突”,如果沖突,則改變位置,直至所有皇后放置完畢。
測試皇后沖突的函數:isValid();
本文思路比較取巧,使用a[n]記錄N皇后位置。根據皇后放置規則可知,每一行有且只有一個皇后,所以從第一行到第N行,依次放置第n個皇后。a[n]記錄第n個皇后所在列數。即第i個皇后放置在第i行第a[i]列。
參考:http://blog.csdn.net/feixiaoxing/article/details/6877965
具體實現如下(AC 36ms):
class Solution { public: vector<vector<string> > re; //測試在第row行,第row列放置皇后是否有效 int isValid(int *a, int n, int row, int col) { int tmpcol=0; for(int tmprow=0;tmprow<row;tmprow++) { tmpcol = a[tmprow]; if(tmpcol == col)// 同列 return 0; if((tmpcol-col) == (tmprow - row))// 在同一右斜線 return 0; if((tmpcol-col) == (row - tmprow))// 在同一左斜線 return 0; } return 1; } void PrintN(int *a, int n) { vector<string> tmps; for(int i=0;i<n;i++) { string s(n,'.'); s[a[i]]='Q'; tmps.push_back(s); } re.push_back(tmps); } void n_queens(int *a,int n, int index) { for(int i=0;i<n;i++) { if(isValid(a,n,index,i)) { a[index]=i; if(index == n-1) { PrintN(a,n); a[index]=0; return; } n_queens(a,n,index+1); a[index]=0; } } } vector<vector<string> > solveNQueens(int n) { int *a = new int[n]; memset(a,0,sizeof(int)*n); n_queens(a,n,0); return re; } };
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