題目:
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 the number of distinct solutions to the n-queens puzzle.
Example:
Input: 4
Output: 2
Explanation: There are two distinct solutions to the 4-queens puzzle as shown below.
[
[".Q…", // Solution 1
“…Q”,
“Q…”,
“…Q.”],
["…Q.", // Solution 2
“Q…”,
“…Q”,
“.Q…”]
]
解法1:
深搜加剪枝
N皇后問題要保證所有的皇后不在同一列、同一行和同一對角線上,我們一行放一個皇后,當我們最後一行放好皇后的時候,即得到了一種擺法,列的話我們只能窮舉所有的情況,在遍歷列的時候,我們需要查看這個位置是否能放下皇后,方法是:查看之前所有放好的皇后,他們的列是否與當前的皇后衝突,以及對角線是否衝突,我們用pos[row] = col,記錄在row行的皇后的列爲col,初始值爲0,這樣的話爲了避免衝突,我們的行和列均從1開始(其實也可以初始值爲-1,這樣行和列均從0開始,設爲0主要是考慮java默認值爲 0,可以不用重新設),對角線是否衝突我們可以使用兩個皇后的行之差的絕對值和列之差的絕對值是否相等來判斷,放完一個皇后後,記錄其位置然後繼續在下一行找新的皇后
class Solution {
public:
int count = 0;
int totalNQueens(int n) {
vector<int> pos(n+1,0);
dfs(pos , 1 ,n );
return count;
}
void dfs(vector<int>& pos, int row, int n){
if(row == n + 1){
count++;
return;
}
for(int col = 1; col <= n; col++){
if(!isVaild(pos,row,col)) continue;
pos[row] = col;
dfs(pos,row + 1,n);
pos[row] = 0;
}
}
bool isVaild(vector<int>& pos, int row, int col){
for(int i = 1; i < row; i++){
if(col == pos[i] || abs(row - i) == abs(col - pos[i])){
return false;
}
}
return true;
}
};
java:
class Solution {
int count = 0;
public int totalNQueens(int n) {
int[] pos = new int[n+1];
dfs(pos , 1 ,n);
return count;
}
private void dfs(int[] pos, int row, int n){
if(row == n + 1){
count++;
return;
}
for(int col = 1; col <= n; col++){
if(!isVaild(pos,row,col)) continue;
pos[row] = col;
dfs(pos,row + 1,n);
pos[row] = 0;
}
}
private boolean isVaild(int[] pos, int row, int col){
for(int i = 1; i < row; i++){
if(col == pos[i] || Math.abs(row - i) == Math.abs(col - pos[i])){
return false;
}
}
return true;
}
}
python:
class Solution(object):
def totalNQueens(self, n):
"""
:type n: int
:rtype: int
"""
self.count = 0
pos = [0] * (n + 1)
self.dfs(pos , 1 ,n)
return self.count
def dfs(self, pos, row, n):
if row == n + 1:
self.count += 1
return
for col in xrange(1,n+1):
if not self.isVaild(pos,row,col): continue
pos[row] = col
self.dfs(pos,row + 1,n)
pos[row] = 0
def isVaild(self,pos, row, col):
for i in xrange(1,row):
if col == pos[i] or abs(row - i) == abs(col - pos[i]):
return False
return True
解法2:
考慮到我們不需要記錄具體皇后的位置,所以我們只需要查看列和對角線是否被佔用
所以我們需要開三個數組,分別記錄列、主對角線和副對角線有沒有被佔用,
我們觀察得知,處於同一主對角線的行與列的差相同,但是差值有可能爲負數,所以我們要加上n使之成爲正數(作爲數組的下標)
處於同一副對角線的行與列的和相同
c++:
class Solution {
public:
int count = 0;
int totalNQueens(int n) {
vector<bool> cols(n), diag(2 * n), anti_diag(2 * n);
dfs(cols,diag,anti_diag,0,n);
return count;
}
void dfs(vector<bool>& cols, vector<bool>& diag, vector<bool>& anti_diag, int row, int n){
if(row == n){
count++;
return;
}
for(int col = 0; col < n; col++){
int idx1 = row - col + n;
int idx2 = row + col;
if(cols[col] || diag[idx1] || anti_diag[idx2]) continue;
cols[col] = diag[idx1] = anti_diag[idx2] = true;
dfs(cols,diag,anti_diag,row + 1,n);
cols[col] = diag[idx1] = anti_diag[idx2] = false;
}
}
};
java:
class Solution {
int count = 0;
public int totalNQueens(int n) {
boolean[] cols = new boolean[n];
boolean[] diag = new boolean[2*n];
boolean[] anti_diag = new boolean[2*n];
dfs(cols,diag,anti_diag,0,n);
return count;
}
private void dfs(boolean[] cols,boolean[] diag,boolean[] anti_diag, int row, int n){
if(row == n){
count++;
return;
}
for(int col = 0; col < n; col++){
int idx1 = row - col + n;
int idx2 = row + col;
if(cols[col] || diag[idx1] || anti_diag[idx2]) continue;
cols[col] = diag[idx1] = anti_diag[idx2] = true;
dfs(cols,diag,anti_diag,row + 1,n);
cols[col] = diag[idx1] = anti_diag[idx2] = false;
}
}
}
python:
class Solution(object):
def totalNQueens(self, n):
"""
:type n: int
:rtype: int
"""
self.count = 0
cols = [False] * n
diag = [False] * 2 *n
anti_diag = [False] * 2 * n
self.dfs(cols,diag,anti_diag,0,n)
return self.count
def dfs(self, cols,diag,anti_diag, row, n):
if row == n:
self.count += 1
return
for col in xrange(n):
idx1 = row - col + n;
idx2 = row + col;
if cols[col] or diag[idx1] or anti_diag[idx2]: continue
cols[col] = diag[idx1] = anti_diag[idx2] = True
self.dfs(cols,diag,anti_diag,row + 1,n)
cols[col] = diag[idx1] = anti_diag[idx2] = False