N-Queens
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.."] ]
Naive Way: 这道题可以直观感受到并不是巧妙的算法的,应该是要brute force遍历所有情况。
对于这种题,类似的还有解数独那道题,我都是想到DFS来解的。
但同样是DFS,解法的复杂性,所用的空间大小,back trace的难度,都是很值得想的。
这是我的解法。使用了一个矩阵做容器,DFS遍历,带回溯,每次放置一个Q,对应覆盖位置+1,
回溯时每一个Q的对应覆盖位置-1。每次都检测是否填完,填完则记录进结果。运行时间在所有用Java
的人中排在后面。
class Node{
int x, y;
Node(int a,int b){x = a;y = b;}
}
public List<String[]> solveNQueens(int n) {
List<String[]> rlst = new ArrayList<String[]>();
Stack<Node> stack = new Stack<Node>();
char[][] board = new char[n][n];
for(int i = 0;i < n;i++){for(int j = 0;j < n;j++){board[i][j] = '0';}}
// initialize stack
for(int i = 0;i < n;i++){
Node node = new Node(0,i);
stack.push(node);
}
// DFS
while(!stack.isEmpty()){
Node node = stack.pop();
board[node.x][node.y] = 'Q';
boolean hasNext = false;
// set new Q
addBoard(board, node.x, node.y);
if(isFinished(board) && node.x==n-1){
String[] strs = new String[n];
for(int i = 0;i < n;i++){
StringBuilder str = new StringBuilder();
for(int j = 0;j < n;j++)
str.append(board[i][j]=='Q'?'Q':'.');
strs[i] = str.toString();
}
rlst.add(strs);
}
// push next row
if(node.x+1 < n){
for(int j = 0;j < n;j++){
if(board[node.x+1][j]=='0'){
Node next = new Node(node.x+1,j);
stack.push(next);
hasNext = true;
}
}
}
if(!hasNext || (isFinished(board) && node.x==n-1)){
// back trace
if(!stack.isEmpty()){
Node peek = stack.peek();
for(int i = node.y;i >= 0;i--)
if(board[node.x][i]=='Q')
minusBoard(board,node.x,i);
for(int i = node.x-1;i >= peek.x;i--)
for(int j = n-1;j >= 0;j--)
if(board[i][j] =='Q')
minusBoard(board,i,j);
}
}
}
return rlst;
}
private boolean isFinished(char[][] b){
for(int i = 0;i < b.length;i++)
for(int j = 0;j < b[0].length;j++)
if(b[i][j]== '0')
return false;
return true;
}
private void addBoard(char[][] b, int x, int y){
for(int i = 0;i < b.length;i++)
b[i][y] = b[i][y]=='Q'?b[i][y]:(char)(b[i][y]+1);
for(int j = 0;j < b[0].length;j++)
b[x][j] = b[x][j]=='Q'?b[x][j]:(char)(b[x][j]+1);
for(int i = 1;i < b.length;i++){
if(x+i >= 0 && x+i < b.length && y+i >= 0 && y+i < b[0].length)
b[x+i][y+i] = b[x+i][y+i]=='Q'?b[x+i][y+i]:(char)(b[x+i][y+i]+1);
if(x+i >= 0 && x+i < b.length && y-i >= 0 && y-i < b[0].length)
b[x+i][y-i] = b[x+i][y-i]=='Q'?b[x+i][y-i]:(char)(b[x+i][y-i]+1);
if(x-i >= 0 && x-i < b.length && y+i >= 0 && y+i < b[0].length)
b[x-i][y+i] = b[x-i][y+i]=='Q'?b[x-i][y+i]:(char)(b[x-i][y+i]+1);
if(x-i >= 0 && x-i < b.length && y-i >= 0 && y-i < b[0].length)
b[x-i][y-i] = b[x-i][y-i]=='Q'?b[x-i][y-i]:(char)(b[x-i][y-i]+1);
}
return;
}
private void minusBoard(char[][] b, int x, int y){
for(int i = 0;i < b.length;i++)
b[i][y] = b[i][y]=='Q'?b[i][y]:(char)(b[i][y]-1);
for(int j = 0;j < b[0].length;j++)
b[x][j] = b[x][j]=='Q'?b[x][j]:(char)(b[x][j]-1);
for(int i = 1;i < b.length;i++){
if(x+i >= 0 && x+i < b.length && y+i >= 0 && y+i < b[0].length)
b[x+i][y+i] = b[x+i][y+i]=='Q'?b[x+i][y+i]:(char)(b[x+i][y+i]-1);
if(x+i >= 0 && x+i < b.length && y-i >= 0 && y-i < b[0].length)
b[x+i][y-i] = b[x+i][y-i]=='Q'?b[x+i][y-i]:(char)(b[x+i][y-i]-1);
if(x-i >= 0 && x-i < b.length && y+i >= 0 && y+i < b[0].length)
b[x-i][y+i] = b[x-i][y+i]=='Q'?b[x-i][y+i]:(char)(b[x-i][y+i]-1);
if(x-i >= 0 && x-i < b.length && y-i >= 0 && y-i < b[0].length)
b[x-i][y-i] = b[x-i][y-i]=='Q'?b[x-i][y-i]:(char)(b[x-i][y-i]-1);
}
b[x][y] = '0';
return;
}
Improved Way:N Queens II
No comments:
Post a Comment