LeetCode——N皇后 II

Q:n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给定一个整数 n,返回 n 皇后不同的解决方案的数量。

示例:
输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]

提示:皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一或七步,可进可退。(引用自 百度百科 - 皇后 )

A:
同I中的回溯法

    private int result;

    public int totalNQueens(int n) {
        if (n <= 1)
            return n;
        ArrayList<Integer> l = new ArrayList<>();
        result = 0;
        help(0, n, l);
        return result;
    }

    private void help(int row, int n, ArrayList<Integer> l) {
        if (row == n) {
            result++;
            return;
        }
        for (int col = 0; col < n; col++) {
            if (!l.contains(col)) {
                if (!isDiagonal(l, col)) {
                    l.add(col);
                    help(row + 1, n, l);
                    l.remove(l.size() - 1);
                }
            }
        }
    }

    private boolean isDiagonal(ArrayList<Integer> l, int col) {
        int currRow = l.size();
        for (int row = 0; row < l.size(); row++) {
            if (Math.abs(currRow - row) == Math.abs(col - l.get(row))) {
                return true;
            }
        }
        return false;
    }

2.如果是面试,上面那种就ok了。还有一种位运算的方法,(但我位运算学的一直不好,就没仔细看)
借鉴:使用 bitmap 回溯

  public int backtrack(int row, int hills, int next_row, int dales, int count, int n) {
    /** 
     row: 当前放置皇后的行号
     hills: 主对角线占据情况 [1 = 被占据,0 = 未被占据]
     next_row: 下一行被占据的情况 [1 = 被占据,0 = 未被占据]
     dales: 次对角线占据情况 [1 = 被占据,0 = 未被占据]
     count: 所有可行解的个数
     */

    // 棋盘所有的列都可放置,
    // 即,按位表示为 n 个 '1'
    // bin(cols) = 0b1111 (n = 4), bin(cols) = 0b111 (n = 3)
    // [1 = 可放置]
    int columns = (1 << n) - 1;

    if (row == n)   // 如果已经放置了 n 个皇后
      count++;  // 累加可行解
    else {
      // 当前行可用的列
      // ! 表示 0 和 1 的含义对于变量 hills, next_row and dales的含义是相反的
      // [1 = 未被占据,0 = 被占据]
      int free_columns = columns & ~(hills | next_row | dales);

      // 找到可以放置下一个皇后的列
      while (free_columns != 0) {
        // free_columns 的第一个为 '1' 的位
        // 在该列我们放置当前皇后
        int curr_column = - free_columns & free_columns;

        // 放置皇后
        // 并且排除对应的列
        free_columns ^= curr_column;

        count = backtrack(row + 1,
                (hills | curr_column) << 1,
                next_row | curr_column,
                (dales | curr_column) >> 1,
                count, n);
      }
    }

    return count;
  }
  public int totalNQueens(int n) {
    return backtrack(0, 0, 0, 0, 0, n);
  }
原文地址:https://www.cnblogs.com/xym4869/p/13139421.html