题目:
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.."] ]
思路:
1) 递归,每次递归时把横竖斜方向的位置设置为"Forbidden"区域
package recursion; import java.util.ArrayList; import java.util.List; public class NQueens { public List<List<String>> solveNQueens(int n) { char[][] board = new char[n][n]; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { board[i][j] = '.'; } } List<List<String>> res = new ArrayList<List<String>>(); solve(res, 0, board, n); return res; } private void solve(List<List<String>> res, int row, char[][] board, int n) { if (row >= n) { List<String> record = new ArrayList<String>(); for (int i = 0; i < n; ++i) { StringBuilder sb = new StringBuilder(); for (int j = 0; j < n; ++j) { if (board[i][j] != 'Q') board[i][j] = '.'; sb.append(board[i][j]); } record.add(sb.toString()); } res.add(record); return; } for (int i = 0; i < n; ++i) { if (board[row][i] == '.') { char[][] cpyBoard = copyBoard(board, n); setForbiddenArea(cpyBoard, row, i, n); solve(res, row + 1, cpyBoard, n); } } } private void setForbiddenArea(char[][] board, int i, int j, int n) { // Rows and columns for (int k = 0; k < n; ++k) { board[i][k] = 'F'; board[k][j] = 'F'; } // Diagonal for (int k = 1 - n; k <= n - 1; ++k) { if (i + k >= 0 && i + k < n && j + k >= 0 && j + k < n) board[i + k][j + k] = 'F'; if (i + k >= 0 && i + k < n && j - k >= 0 && j - k < n) board[i + k][j - k] = 'F'; } board[i][j] = 'Q'; } private char[][] copyBoard(char[][] board, int n) { char[][] cpyBoard = new char[n][n]; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) cpyBoard[i][j] = board[i][j]; } return cpyBoard; } public static void main(String[] args) { // TODO Auto-generated method stub NQueens n = new NQueens(); List<List<String>> res = n.solveNQueens(4); for (List<String> subRes : res) { for (String s : subRes) System.out.print(s + " "); System.out.println(" "); } } }
2) 用一个一维数组来存储每行对应的Q的位置,i代表第i行,rows[i]代表Q的位置。
package recursion; import java.util.ArrayList; import java.util.List; public class NQueens { public List<List<String>> solveNQueens(int n) { List<List<String>> res = new ArrayList<List<String>>(); int[] positions = new int[n]; solve(positions, res, 0, n); return res; } private void solve(int[] positions, List<List<String>> res, int row, int n) { if (row == n) { List<String> record = new ArrayList<String>(); for (int i = 0; i < n; ++i) { StringBuilder sb = new StringBuilder(); for (int j = 0; j < n; ++j) sb.append('.'); sb.setCharAt(positions[i], 'Q'); record.add(sb.toString()); } res.add(record); } else { for (int i = 0; i < n; ++i) { if (isValid(positions, row, i)) { positions[row] = i; solve(positions, res, row + 1, n); } } } } private boolean isValid(int[] positions, int row, int candidate) { for (int i = 0; i < row; ++i) { if (positions[i] == candidate || Math.abs(i - row) == Math.abs(positions[i] - candidate)) return false; } return true; } public static void main(String[] args) { // TODO Auto-generated method stub NQueens n = new NQueens(); List<List<String>> res = n.solveNQueens(4); for (List<String> subRes : res) { for (String s : subRes) System.out.print(s + " "); System.out.println(" "); } } }