zoukankan      html  css  js  c++  java
  • 力扣No.51 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;
        }
    }

  • 相关阅读:
    Combine 框架,从0到1 —— 4.在 Combine 中使用计时器
    Combine 框架,从0到1 —— 4.在 Combine 中使用通知
    Combine 框架,从0到1 —— 3.使用 Subscriber 控制发布速度
    Combine 框架,从0到1 —— 2.通过 ConnectablePublisher 控制何时发布
    使用 Swift Package Manager 集成依赖库
    iOS 高效灵活地配置可复用视图组件的主题
    构建个人博客网站(基于Python Flask)
    Swift dynamic关键字
    Swift @objcMembers
    仅用递归函数操作逆序一个栈(Swift 4)
  • 原文地址:https://www.cnblogs.com/RS-Sakura/p/13932382.html
Copyright © 2011-2022 走看看