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.

原文地址:https://www.cnblogs.com/wentiliangkaihua/p/10487182.html