n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回 n 皇后不同的解决方案的数量。
示例:
输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
[
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
思路:详见:皇后问题详细解释。
public class Solution {public int totalNQueens(int n) {// 因为本方法中位运算的载体是int型变量,所以该方法只能算1~32皇后问题// 如果想计算更多的皇后问题,需使用包含更多位的变量if (n < 1 || n > 32) {return 0;}int upperLim = n == 32 ? -1 : (1 << n) - 1;//upperLim的作用为棋盘大小,比如8皇后为00000000 00000000 00000000 11111111//32皇后为11111111 11111111 11111111 11111111return process2(upperLim, 0, 0, 0);}public int process2(int upperLim, int colLim, int leftDiaLim,int rightDiaLim) {if (colLim == upperLim) {return 1;}int pos = 0; //pos:所有的合法位置int mostRightOne = 0; //所有合法位置的最右位置//所有记录按位或之后取反,并与全1按位与,得出所有合法位置pos = upperLim & (~(colLim | leftDiaLim | rightDiaLim));int res = 0;//计数while (pos != 0) {mostRightOne = pos & (~pos + 1);//取最右的合法位置pos = pos - mostRightOne; //去掉本位置并尝试res += process2(upperLim, //全局colLim | mostRightOne, //列记录//之前列+本位置(leftDiaLim | mostRightOne) << 1, //左斜线记录//(左斜线变量+本位置)左移 (rightDiaLim | mostRightOne) >>> 1); //右斜线记录//(右斜线变量+本位置)右移(高位补零)}return res;}
}