zoukankan      html  css  js  c++  java
  • 51. 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.

    Example:

    Input: 4
    Output: [
     [".Q..",  // Solution 1
      "...Q",
      "Q...",
      "..Q."],
    
     ["..Q.",  // Solution 2
      "Q...",
      "...Q",
      ".Q.."]
    ]
    Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.

    经典的递归(dfs)问题,要求棋盘上的皇后不能两两在同一行,同一列,或者对角线上,打印出所有的解法

    图转自https://blog.csdn.net/you_will_know_me/article/details/78419088

    *****判断在不在一条对角线上,即有两棋子坐标分别为(X1,Y1),(X2,Y2),则|X1-X2|!=|Y1-Y2|。

    参考之后,整个代码将分为几个部分:

    1. 得出一个解,创建一个长度为n的全是" . "的数组,然后填充“Q”。

    2. dfs本体:从0到n,一行一行寻找合适的位置放Q,用到isValid函数

    3. isValid函数,用来判断当前位置可否正常放Q

    public class Solution {
        public List<List<String>> solveNQueens(int n) {
            List<List<String>> result = new ArrayList<>();
            int[] C = new int[n]; // C[i]表示第i行皇后所在的列编号
            dfs(C, 0, result);
            return result;
        }
        private static void dfs(int[] C, int row, List<List<String>> result) {
            final int N = C.length;
            if (row == N) { // 终止条件,也是收敛条件,意味着找到了一个可行解
                List<String> solution = new ArrayList<>();
                for (int i = 0; i < N; ++i) {
                    char[] charArray = new char[N];
                    Arrays.fill(charArray, '.');
                    for (int j = 0; j < N; ++j) {
                        if (j == C[i]) charArray[j] = 'Q';
                    }
                    solution.add(new String(charArray));
                }
                result.add(solution);
                return;
            }
    
            for (int j = 0; j < N; ++j) {  // 扩展状态,一列一列的试
                final boolean ok = isValid(C, row, j);
                if (!ok) continue;  // 剪枝,如果非法,继续尝试下一列
                // 执行扩展动作
                C[row] = j;
                dfs(C, row + 1, result);
                // 撤销动作
                // C[row] = -1;
            }
        }
    
        /**
         * 能否在 (row, col) 位置放一个皇后.
         *
         * @param C 棋局
         * @param row 当前正在处理的行,前面的行都已经放了皇后了
         * @param col 当前列
         * @return 能否放一个皇后
         */
        private static boolean isValid(int[] C, int row, int col) {
            for (int i = 0; i < row; ++i) {
                // 在同一列
                if (C[i] == col) return false;
                // 在同一对角线上
                if (Math.abs(i - row) == Math.abs(C[i] - col)) return false;
            }
            return true;
        }
    }
    class Solution {
        public List<List<String>> solveNQueens(int n) {
            List<List<String>> res = new ArrayList();
            int[] q = new int[n];
            dfs(res, q, 0, n);
            return res;
        }
        
        public void dfs(List<List<String>> res, int[] q, int start, int n) {
            if(start == n) {
                List<String> cur = new ArrayList();
                for(int i = 0; i < n; i++) {
                    char[] ch = new char[n];
                    Arrays.fill(ch, '.');
                    ch[q[i]] = 'Q';
                    cur.add(new String(ch));
                }
                res.add(cur);
                return;
            }
            else {
                for(int i = 0; i < n; i++) {
                    if(!isValid(start, i, q)) continue;
                    q[start] = i;
                    dfs(res, q, start+1, n);
                    q[start] = 0;
                }
            }
        }
        
        public boolean isValid(int ro, int co, int[] q) {
            for(int i = 0; i < ro; i++) {
                if(co == q[i] || Math.abs(i - ro) == Math.abs(q[i] - co)) return false;
            }
            return true;
        }
    }

    总结:

    This is a typical backtracking question, we want to try every possible solution and get invalid ones.

    So like normally we set a variable start means the level we current in. And an array int[ ] q whose length is n, means in i-th level we set queen in q[i] place.

    The isValid method is to check if current position is okay to set queen, it basically check from row 0 to row (ro - 1), cuz ro is the row we want to put queen. So we just check if queen is in conflict vertically or diagnonally by check (co == q [ i ] || (i - ro) == (q[i] - co)

    When we have a valid answer, create n char array and set relevant queen to it, then convert to string and store in result.

  • 相关阅读:
    第十二周作业
    第11周学习总结
    第十周学习总结(五一作业)
    第九周作业
    第八周作业
    第七周作业
    PAT1049、1048、1047
    例题3-5,例题4-2,例题4-3
    PAT甲级真题打卡:1002. A+B for Polynomials
    PAT甲级真题打卡:1001.A+B Format
  • 原文地址:https://www.cnblogs.com/wentiliangkaihua/p/10487182.html
Copyright © 2011-2022 走看看