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