n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位
示例:
输入:4 输出:[ [".Q..", // 解法 1 "...Q", "Q...", "..Q."], ["..Q.", // 解法 2 "Q...", "...Q", ".Q.."] ] 解释: 4 皇后问题存在两个不同的解法。
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
==================================================================================================
国际象棋中的皇后可以攻击一行、一列和斜线范围内的目标,因此下一行皇后的摆放需要考虑避开上面皇后的攻击范围。最终解法需要每一行都要有一个皇后,可能存在多种解法。这道题可以用回溯的方法来解决,从上往下搜索可能的解法,如果能到达底层则该解法成功,将其放入输出列表。如果发现某一行的某个位置与上面冲突,就往右搜索下一个;如果整行都找不到合适的解,就递归返回上一层再往下搜索。
代码:
class Solution { public List<List<String>> solveNQueens(int n) { char[][] chess = new char[n][n]; //先将矩阵置'.' for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { chess[i][j] = '.'; } } List<List<String>> res = new ArrayList<>(); dfs(0, chess, res); return res; } private void dfs(int row, char[][] chess, List<List<String>> res) { //如果能到达底层就加入结果 if (row == chess.length) { res.add(construct(chess)); } //每一行都从左往右搜索 for (int col = 0; col < chess.length; col++) { //判断是否冲突 if (isValid(chess, row, col)){ chess[row][col] = 'Q'; dfs(row + 1, chess, res); chess[row][col] = '.'; } } } private boolean isValid(char[][] chess, int row, int col) { //判断这一列上面有没有皇后 for (int i = 0; i < row; i++) { if (chess[i][col] == 'Q') { return false; } } //判断此位置右上角有没有皇后 for (int i = row - 1, j = col + 1; i >= 0 && j < chess.length; i--, j++) { if (chess[i][j] == 'Q') { return false; } } //判断此位置左上角有没有皇后 for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { if (chess[i][j] == 'Q') { return false; } } return true; } //把将char[][]转换为List<String> private List<String> construct(char[][] chess) { List<String> path = new ArrayList<>(); for (int i = 0; i < chess.length; i++) { path.add(new String(chess[i])); } return path; } }