LeetCode 51. N-Queens(dfs)

题目来源:https://leetcode.com/problems/n-queens/

问题描述

51. N-Queens

Hard

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.

------------------------------------------------------------

题意

N皇后问题。在N×N的棋盘上放N个皇后,使得她们不会互相攻击。

------------------------------------------------------------

思路

dfs深搜。一开始我的思路是遍历每一个单元格,考察是否可以放皇后,再用两种剪枝方法(如果有一整行不能放皇后则返回;如果一行已经放了皇后则跳到下一行)进行剪枝。

后来在同学的提醒下,想到由于每行只能放一个皇后,所以可以用一个onehot的mask表示每行皇后的位置,然后用位运算可以方便地实现搜索。

另外需要注意位运算的优先级比==低,要勤加括号~

------------------------------------------------------------

代码

【对每个单元格进行搜索的代码】

class Solution {
    private List<List<String>> ans = new LinkedList<>();
    private int n;
    private boolean[][] board;
    private boolean[] row_mark;
    private boolean[] col_mark;
    private boolean[] sub_mark;
    private boolean[] sum_mark;
    private boolean[] edit_row;
    private int cnt;
    
    private void init(int n)
    {
        this.n = n;
        this.cnt = 0;
        this.board = new boolean[n][n];
        this.row_mark = new boolean[n];
        this.col_mark = new boolean[n];
        this.sub_mark = new boolean[2*n-1];
        this.sum_mark = new boolean[2*n-1];
        this.edit_row = new boolean[n];
    }
    
    private static List<String> board2ans(boolean[][] board)
    {
        List<String> ret = new ArrayList<String>();
        for (boolean[] row: board)
        {
            StringBuilder sb = new StringBuilder();
            for (boolean item: row)
            {
                if (item)
                {
                    sb.append("Q");
                }
                else
                {
                    sb.append(".");
                }
            }
            ret.add(sb.toString());
        }
        return ret;
    }
    
    private void dfs(int x, int y)
    {
        if (x == this.n)
        {
            if (this.cnt == this.n)
            {
                ans.add(board2ans(this.board));
            }
            return;
        }
        if (x > 0 && !this.edit_row[x-1])
        {
            return;
        }
        if (this.edit_row[x])
        {
            dfs(x+1, 0);
            return;
        }
        if (!this.row_mark[x] && !this.col_mark[y] && !this.sub_mark[x-y+n-1] && !this.sum_mark[x+y])
        {
            this.board[x][y] = true;
            this.row_mark[x] = true;
            this.col_mark[y] = true;
            this.sub_mark[x-y+n-1] = true;
            this.sum_mark[x+y] = true;
            this.edit_row[x] = true;
            this.cnt++;
            if (y == this.n-1)
            {
                dfs(x+1, 0);
            }
            else
            {
                dfs(x, y+1);
            }
            this.board[x][y] = false;
            this.row_mark[x] = false;
            this.col_mark[y] = false;
            this.sub_mark[x-y+n-1] = false;
            this.sum_mark[x+y] = false;
            this.edit_row[x] = false;
            this.cnt--;
        }
        if (y == this.n-1)
        {
            dfs(x+1, 0);
        }
        else
        {
            dfs(x, y+1);
        }
    }
    
    public List<List<String>> solveNQueens(int n) {
        if (n == 0)
        {
            return new LinkedList() {
                {
                    add(Collections.emptyList());
                }
            };
        }
        init(n);
        dfs(0, 0);
        return this.ans;
    }
}

【对每行的mask进行搜索的代码】

class Solution {
    private List<List<String>> ans = new LinkedList<>();
    private int n;
    private int[] mask;
    private boolean[] col_mark;
    private boolean[] sub_mark;
    private boolean[] sum_mark;
    
    private void init(int n)
    {
        this.n = n;
        this.mask = new int[n];
        this.col_mark = new boolean[n];
        this.sub_mark = new boolean[2*n-1];
        this.sum_mark = new boolean[2*n-1];
    }
    
    private List<String> mask2ans(int[] mask)
    {
        List<String> ret = new ArrayList<String>();
        int N = mask.length, i = 0, bit = 1;
        for (int row: mask)
        {
            StringBuilder sb = new StringBuilder();
            bit = 1;
            for (i=0; i<N; i++)
            {
                if ((row & bit) == 0)
                {
                    sb.append(".");
                }
                else
                {
                    sb.append("Q");
                }
                bit <<= 1;
            }
            ret.add(sb.toString());
        }
        return ret;
    }
    
    public void dfs(int x)
    {
        if (x == n)
        {
            this.ans.add(mask2ans(mask));
            return;
        }
        int y = 0, bit = 1;
        for (y=0; y<this.n; y++)
        {
            if (!this.col_mark[y] && !this.sub_mark[x-y+n-1] && !this.sum_mark[x+y])
            {
                this.mask[x] = bit;
                this.col_mark[y] = true;
                this.sub_mark[x-y+n-1] = true;
                this.sum_mark[x+y] = true;
                dfs(x+1);
                this.col_mark[y] = false;
                this.sub_mark[x-y+n-1] = false;
                this.sum_mark[x+y] = false;
            }
            bit <<= 1;
        }
    }
    
    public List<List<String>> solveNQueens(int n) {
        if (n == 0)
        {
            return new LinkedList() {
                {
                    add(Collections.emptyList());
                }
            };
        }
        init(n);
        dfs(0);
        return ans;
    }
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/89207324