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.."]
]
Python 递归 Version:
class Solution:
def IsValid(self, posDict, col, row):
if col in posDict:
return False
for hc,hr in posDict.items():
if abs(hc-col) == abs(hr-row):
return False
return True
def BackTrack(self, posDict, curRow, n):
if (curRow == n):
return 1
res = 0
for i in range(n):
if (self.IsValid(posDict, i, curRow)):
posDict1 = dict(posDict)
posDict1[i] = curRow
res += self.BackTrack(posDict1, curRow+1, n)
return res
def totalNQueens(self, n):
res = self.BackTrack({}, 0, n)
return res
Backtracks are usually written as recursive programs, the general solution is :
void backtrack(int t) {
if (t > n)
output(x);
else
for (int i = f(n, t); i <= g(n,t); ++i) {
x[t] = h(i);
if (constraint(t) && bound(t))
backtrack(t + 1);
}
}
t stands for the recursive depth, f(n, t) is the starting number of next layer, g(n, t) is the ending number of next layer. Bound is a function for pruning.
But sometimes, non-recursive programs are essential:
void iterativeBacktrack() {
int t = 0;
while (t > -1) {
if (t == n && solution(t))
output(x);
if (f(n, t) + 1 <= g(n, t)){
f(n, t) = f(n, t) + 1;
if (constraint(t) && bound(t))
++t;
}
}
else
--t;
}
}
Python非递归Version:
class Solution:
def IsValid(self, posDict, col, row):
for hr, hc in posDict.items():
if abs(hc - col) == abs(hr - row) or col == hc:
return False
return True
def BackTrack2(self, posDict, curRow, n):
res = 0
rowStatus = [0 for i in range(n)]
while (curRow > -1):
if (curRow == n):
res += 1
curRow -= 1
if (rowStatus[curRow] >= -1 and rowStatus[curRow] < n):
rowStatus[curRow] += 1
if (self.IsValid(posDict, rowStatus[curRow], curRow)):
posDict[curRow] = rowStatus[curRow]
curRow +=1
elif (rowStatus[curRow] == n):
if curRow in posDict:
posDict.pop(curRow)
rowStatus[curRow] = 0
curRow -= 1
return res
def totalNQueens(self, n):
res = self.BackTrack2({}, 0, n)
return res
s = Solution()
print(s.totalNQueens(4))
C++ 位运算递归 Version:
class Solution {
public:
unsigned int upperlimit;
int res = 0;
void dfs(unsigned int row, unsigned int ld, unsigned int rd) {
if (row == upperlimit) {
++res;
return;
}
unsigned int pos = (row | ld | rd) & upperlimit, p = (~pos) & upperlimit, digit;
while (p) {
digit = p - (p & (p - 1));
dfs(row + digit, (ld + digit) << 1, (rd + digit) >> 1);
p -= digit;
}
};
int totalNQueens(int n) {
upperlimit = 0;
for (int i = 0; i < n; ++i)
upperlimit |= (1 << i);
res = 0;
dfs(0, 0, 0);
return res;
}
};