八皇后问题主要是:在一个8*8的棋盘上,放置八个皇后,这八个皇后不能处在同一行、同一列以及统一斜线,问符合要求的安置方法有多少种情况?
高斯说64种,随着计算机的高速发展,而今人类用计算机计算得出的记过是92种,那我们是如何借助计算机实现的呢?
首先,我们先聊聊思路
至于图上第4步为什么会回溯呢?
理由是:假设说如第4点的操作,第8个皇后(不一定是第8个皇后,也许是前面的皇后就已经出现了所有列数的安放位置都不符合条件)的安放位置都不符合情况,这时候该递归方法并没有return结束,所以第七个皇后的安放列数仍然向下遍历,故这就解决了回溯的情况。
要点:
1.理论上是需要创建一个二维数组来记录棋盘的,但是这里数组比较多位置会是没有落子的,即都为0 既为了节省空间,也为了简便,故我们这里可以直接创建一个一维数组 下标代表行数,数组内的值代表列数,如arr[1]=3,即代表落子在第一行第三列
2.这里判断是否在同一斜线上,我们通过一个数学结论去判断:如果对角线的行之差的绝对值等于列之差的绝对值,则在同一斜线上
下面附上具体代码实现
package com.liu.recursion;
/**
* @author liuweixin
* @create 2021-09-09 16:15
*/
//处理八皇后问题
public class Queue8 {
//先创建一个棋盘
//理论上是需要创建一个二维数组,但是这里数组比较多位置会是没有落子的
//既为了节省空间,也为了简便,故我们这里可以直接创建一个一维数组
// 下标代表行数,数组内的值代表列数,如arr[1]=3,即代表落子在第一行第三列
int[] arr;//用于储存八皇后放置的结果
int maxSize = 8;//皇后的数量
int count;//记录八皇后的数
public Queue8() {
arr = new int[maxSize];
}
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
queue8.dealQueue8(0);
System.out.println("八皇后结果的总数为:"+queue8.count);
}
/**
* 处理八皇后问题
* 八个皇后不能处于同一行、同一列、同一斜线
*
* @param n 安放第n个皇后
*/
public void dealQueue8(int n) {
if(n==maxSize){
//此时八皇后已经安放好
// System.out.println("八皇后的位置已经安放好");
count++;//每进入这个判断一次,就是一种结果
show();
return;
}else{
for (int i = 0; i < arr.length; i++) {
arr[n]=i;//因为这是第n个皇后,所以也就在对应的第n行,我们遍历安放列数
//判断安放位置是否冲突
if(check(n)){
//此时不冲突,则安放下一个
dealQueue8(n+1);
}
//如果冲突,就会通过循环把n放在下一列,然后循环比较
}
}
}
/**
* 检查放置的第n个皇后是否符合要求
*
* @param n 传入的第n个皇后
* @returni 如果符合要求,则返回true
*/
public boolean check(int n) {
for (int i = 0; i < n; i++) {
if (arr[i] == arr[n] || (Math.abs(n - i) == Math.abs(arr[n] - arr[i]))) {
//判断是否在同一列或者在统一斜线
//对角线的行之差的绝对值等于列之差的绝对值,此时为在统一斜线上
return false;
}
}
return true;
}
/**
* 遍历八皇后结果
*/
public void show(){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
}