体验回溯过程
1)搜索到一个结果后,最后一个皇后会继续它的for循环,找新位置(列数+1)。如果新位置满足摆放条件,则说明搜索到了一个新结果。
2)当棋盘最后一行的for循环结束后,会退回到上一行的for循环,为上一行的皇后找新位置,当上一行的皇后找到一个新位置后,会为最后一行的皇后找新位置,当最后一行的皇后找到新位置,就会产生一个结果,按照1)的思想,产生新结果。
重复以上思想,会退回到第一行的for循环。
关键:1、栈顶中的check()方法结束后退回的位置在次顶的for循环里
2、check()方法结束有两种情况:
1)n皇后的for循环结束了,代表n皇后已经judge过所有列
2)最后一个皇后已经check好位置,满足递归结束条件,直接return
2、程序类似于嵌套8个for循环
技巧:判断两个点是否在同一斜线,如果行数差绝对值等于列数差绝对值,则说明在同一斜线
package com.atguigu.recursion;
public class Queen {
//皇后总数量
static int max = 8;
//创建一维数组,保存皇后的位置
static int[] arr = new int[max];
static int count = 0;
static int judgeCount = 0;
public static void main(String[] args) {
Queen queen8 = new Queen();
queen8.check(0);
System.out.println("一共有"+count+"种解法");//92
System.out.println("一共判断了"+judgeCount+"次");//15720
}
/**
* 判断n号皇后是否与已经摆好的皇后冲突,返回false代表冲突,返回true代表不冲突
* @param n n号皇后
*/
public static boolean judge(int n){
judgeCount++;
for (int i = 0; i < n; i++) {
//arr[i] == arr[n] 在同一列
//Math.abs(n-i) == Math.abs(arr[n]-arr[i]) 在同一斜线
//不需要单独判断皇后是否同行,因为传入的n是递增的
if((arr[i] == arr[n]) || Math.abs(n-i) == Math.abs(arr[n]-arr[i])){
return false;
}
}
return true;
}
/**
* 确认n号皇后的位置
* @param n
*/
public static void check(int n){
if(n == max){//说明0~max-1号皇后已经找好位置,此时代表得到了一个解
count++;
print(arr);
return;
}
for (int i = 0; i < max ; i++) {
arr[n] = i;
if(judge(n)){
check(n+1);
}
}
}
/**
* 打印一条摆放结果
*/
public static void print(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
}