N 皇后问题, 简单来说就是:同一行,同一列,同一斜线上,只能存在一个皇后。
搜索策略:每行只放一个皇后,搜索第 i 个皇后可以放在第 i 行的第几列(需要枚举每一列), 放好第 i 个皇后, 才去放第 i+1 个皇后, 直到放完所有皇后。
定义:`f[i]` 代表 第 i 个皇后放置在 第 i 行 第 `f[i]` 列上
每行只放一个皇后,因此不必判断行冲突,有以下约束需要满足:
1. 不能同列,也就是 ` f[i] != f[j] `
2. 不能同斜线,也就是 ` (i-j) != Math.abs(f[i] - f[j]) `
不能同列很好理解,不能同斜线的不等式是啥意思呢?
class Solution {
// 将 count, queens, f[] 设置为成员变量, 方法 dfs() 中不必再传参了。
int count; // 表示 n 皇后问题的可行解的个数
int queens; // 表示 n 个皇后
int[] f; // f[i] 代表 第 i 个皇后放置在 第 i 行 第 f[i] 列上
public int totalNQueens(int n) {
queens = n;
count = 0;
f = new int[n+1];
dfs(1); // 放置第一个皇后
return count;
}
boolean place(int i) { // 判断 第 i 个 皇后是否有容身之地
boolean ok = true;
for(int j = 1; j < i; j++) { // 判断第 i 行的皇后 是否与前 i-1 个皇后的位置冲突了
if(f[i] == f[j] || i-j == Math.abs(f[i] - f[j])){ // 判断是否存在列冲突 和 斜线冲突
ok = false;
break;
}
}
return ok;
}
void dfs(int i) { // 搜索 当前 皇后的位置
if(i > queens) { // 表示已经找到了一个可行解
count++;
} else {
for(int col=1; col<=queens; col++) { // 分别判断每个位置,注意变量 i 不要定义为全局变量,否则递归调用有问题。
f[i] = col;
if(place(i))
dfs(i+1); // 如果不冲突的话,进行下一个皇后的搜索。
}
}
}
}
参考:《趣学算法》——作者陈小玉老师