八皇后问题
- 在8*8的棋盘上摆放八个皇后,使任意两个皇后不处于同一行、同一列或同一斜线上,问有几种摆法?
思路分析
- 把第一个皇后放在第一行第一列
- 第二个放在第二行第一列,判断该位置是否和要求冲突,冲突则将其放在第二行第二列、第三列,直到找到符合要求的位置
- 继续放置第三个,同样一列一列的找到合适的位置,当八个皇后都放置好了位置,就得到一个正解
- 得到正解时,当回退到上一个栈时就会开始回溯,回溯回第一个皇后所在位置时,会将第一个皇后在第一行第一列的所有正解全部找出
- 然后又回继续将第一个皇后放到第一行第二列,循环执行1~4步,直到第一个皇后在第一行的0 ~ 7列所有的正解都找出以后程序停止
- 理论上应该用二维数组模拟棋盘,但是实际上可以通过一个一维数组解决
- 一维数组存放各个皇后处在的列的位置,而该数组的下标为各个皇后所在的行
代码实现
public class Queen8 {
int max=8;
int []array=new int[max];
static int count=0;
public static void main(String[] args) {
Queen8 queen8=new Queen8();
queen8.check(0);
System.out.println(count);
}
/**
* n==8说明已经放置好了八个皇后,因为n从0开始,n==7时说明是在判断第八个皇后应该放置的位置
* 当第一行第一列放置第一个皇后的所有情况都遍历出后,会自动遍历第一行第二列的所有情况
* 直到将第一行的所有列的情况都遍历出来
* @param n
* @return
*/
private void check(int n) {
if(n==max) {
count++;
print();
return;
}
for(int i=0;i<max;i++) {
array[n]=i;
if(judege(n)) {//判断冲突,冲突就让让当前皇后后移一列,不冲突就放置后一个皇后
check(n+1);//让下一个皇后选位置,即开始递归
}
}
}
/**
* array[n]==array[i]相等就表示在同一列
* Math.abs(n-i)==Math.abs(array[n]-array[i])相等就表示在同一斜线上
* n本身就代表行数,而n又是变化的,n必然不等,所以不用判断是否在同一行
* @param n
* @return
*/
private boolean judege(int n) {//判断第n个皇后是否与其他皇后有冲突
for(int i=0;i<n;i++) {
if(array[n]==array[i]||Math.abs(n-i)==Math.abs(array[n]-array[i])) {
return false;
}
}
return true;
}
/**
* 输出结果
*/
private void print() {
for(int i=0;i<max;i++) {
System.out.print(array[i]+" ");
}
System.out.println();
}
}
代码分析
- 每执行一个方法,JVM都会为其分配一个栈空间。这里省略了judge()的栈空间。红色箭头指向因为递归而被创建的方法空间,白色箭头是在某一个栈空间被回收后指向下一个为运行完的方法空间。红色代表递归的前进,白色代表递归的回溯