|
|
package class23;
|
|
|
|
|
|
public class Code03_NQueens {
|
|
|
|
|
|
public static int num1(int n) {
|
|
|
if (n < 1) {
|
|
|
return 0;
|
|
|
}
|
|
|
int[] record = new int[n];
|
|
|
return process1(0, record, n);
|
|
|
}
|
|
|
|
|
|
// 当前来到i行,一共是0~N-1行
|
|
|
// 在i行上放皇后,所有列都尝试
|
|
|
// 必须要保证跟之前所有的皇后不打架
|
|
|
// int[] record record[x] = y 之前的第x行的皇后,放在了y列上
|
|
|
// 返回:不关心i以上发生了什么,i.... 后续有多少合法的方法数
|
|
|
public static int process1(int i, int[] record, int n) {
|
|
|
if (i == n) {
|
|
|
return 1;
|
|
|
}
|
|
|
int res = 0;
|
|
|
// i行的皇后,放哪一列呢?j列,
|
|
|
for (int j = 0; j < n; j++) {
|
|
|
if (isValid(record, i, j)) {
|
|
|
record[i] = j;
|
|
|
res += process1(i + 1, record, n);
|
|
|
}
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
public static boolean isValid(int[] record, int i, int j) {
|
|
|
// 0..i-1
|
|
|
for (int k = 0; k < i; k++) {
|
|
|
if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 请不要超过32皇后问题
|
|
|
public static int num2(int n) {
|
|
|
if (n < 1 || n > 32) {
|
|
|
return 0;
|
|
|
}
|
|
|
// 如果你是13皇后问题,limit 最右13个1,其他都是0
|
|
|
int limit = n == 32 ? -1 : (1 << n) - 1;
|
|
|
return process2(limit, 0, 0, 0);
|
|
|
}
|
|
|
|
|
|
// 7皇后问题
|
|
|
// limit : 0....0 1 1 1 1 1 1 1
|
|
|
// 之前皇后的列影响:colLim
|
|
|
// 之前皇后的左下对角线影响:leftDiaLim
|
|
|
// 之前皇后的右下对角线影响:rightDiaLim
|
|
|
public static int process2(int limit, int colLim, int leftDiaLim, int rightDiaLim) {
|
|
|
if (colLim == limit) {
|
|
|
return 1;
|
|
|
}
|
|
|
// pos中所有是1的位置,是你可以去尝试皇后的位置
|
|
|
int pos = limit & (~(colLim | leftDiaLim | rightDiaLim));
|
|
|
int mostRightOne = 0;
|
|
|
int res = 0;
|
|
|
while (pos != 0) {
|
|
|
mostRightOne = pos & (~pos + 1);
|
|
|
pos = pos - mostRightOne;
|
|
|
res += process2(limit, colLim | mostRightOne, (leftDiaLim | mostRightOne) << 1,
|
|
|
(rightDiaLim | mostRightOne) >>> 1);
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
int n = 15;
|
|
|
|
|
|
long start = System.currentTimeMillis();
|
|
|
System.out.println(num2(n));
|
|
|
long end = System.currentTimeMillis();
|
|
|
System.out.println("cost time: " + (end - start) + "ms");
|
|
|
|
|
|
start = System.currentTimeMillis();
|
|
|
System.out.println(num1(n));
|
|
|
end = System.currentTimeMillis();
|
|
|
System.out.println("cost time: " + (end - start) + "ms");
|
|
|
|
|
|
}
|
|
|
}
|