**
递归方法求八皇后问题
**
- column[]代表列不相同; lead[]代表主对角线不相同; minor[]代表次对角线不相同
- 宏定义Q为皇后数及Q阶棋盘
- 如果两个皇后Q1(x1, y1)和Q2(x2, y2)不符合要求,则以下四个条件之一必符合(这里我的想法是x为列,y为行)
- x1 == x2(表示两个皇后刚好在同一列)
- y1 == y2(表示两个皇后刚好在同一行)
- x1 + y1 == x2 +y2(次对角线)
- x1 - y1 == x2 - y2(主对角线)
- 因为递归方法参数为行,则同一行的可能性不用考虑,只需要考虑列、主对角线和次对角线即可
- 对角线定义的数组容量Q*2+1的理由:次对角线Max为Q+Q,且数组从1开始
public class test_1 {
final int Q = 8; //定义n*n个皇后
//数组中之所以+1,我们的行列从1开始算
int[] column = new int[Q+1]; //列
int[] lead = new int[Q*2+1]; //主对角线
int[] minor = new int[Q*2+1]; //次对角线
int[] queen = new int[Q+1]; //用于打印图形
public int num = 0;
//构造方法,初始化棋盘,清空皇后
public test_1(){
for(int i=1; i <= Q ;i++)
column[i] = 0;
for(int i=1; i <= Q*2; i++){
lead[i] = 0;
minor[i] = 0;
}
}
//递归
void backtrack(int i){
//当i>Q时,结束
if(i>Q){
showAnswer();
}else{
for(int j = 1; j <= Q; j++){
if(column[j] == 0 && lead[i-j+Q] == 0 && minor[i+j] == 0){ //对应相应的i行,j列等等(i行是重点!!)
queen[i] = j; //皇后落点
column[j] = lead[i-j+Q] = minor[i+j] = 1; //相应的列、主对角线、次对角线无法再次占位
backtrack(i+1); //递归i+1行
column[j] = lead[i-j+Q] = minor[i+j] = 0; //没有真实皇后的位置返回0,此时递归到了最后一次
}
}
}
}
//打印所有可能性
void showAnswer(){
num++;
System.out.println("第" + num + "种可能性");
for(int i = 1; i <= Q; i++){
for(int j = 1; j <= Q; j++){
//一个个判断,前面已经为queen[i]赋值
if(queen[i] == j){
System.out.print("Q");
}else{
System.out.print("×");
}
}
System.out.println();
}
}
public static void main(String[] args) {
test_1 queen = new test_1();
queen.backtrack(1);
}
}
花了好长时间理解的八皇后问题,期间还手动推算过,记录一下!