八皇后-递归算法
1.问题表述
在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。
2.思路分析
-
由于二维数组每行只放一个数组,我们可以用一个一维的数组来表示创建一个长度为8的数组,数组的值表示棋子放在第几列。下标0表示第一行,以此类推。例如 04752613 可以表示以下的二维数组。即可表示一个八皇后的解。
1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
-
创建一个judge方法,判断当前棋子是否与前面所摆放的棋子冲突,如果冲突返回false 反之为true。
-
创建一个check方法遍历数组当前行的每一列。调用judge方法判断。如果judge判断为true,继续递归调用check。反之退到上一层。
-
当check到 8 时。说明已经得到一个答案。打印出即可。
3.代码实现
package com.zzd.recursive;
/**
* @Author ZZD
* @Date 2020/7/25 15:47
* @Email 1396896729@qq.com
*/
public class Queen8 {
private int max = 8;
//存储最终的答案 类似04752613
private int[] arr = new int[max];
/**
* @params n 表示当前为第几个皇后
* @return
*/
public void check(int n) {
//如果n == 数组的长度。表示已经摆放完8个棋子。得到一个答案,打印即可。
if (n==max){
print();
return;
}
//有8行所以循环八次。
for (int i = 0; i < max; i++) {
//i表示皇后所在的列的位置,arr[n] = 表示第几个皇后
arr[n] = i;
if (judge(n)){
check(n+1);
}
}
}
/**
* @params
* @return
*
* 判断第n个皇后所放的位置与前面是否有重复的
*/
private boolean judge(int n) {
//从第一行开始遍历。
for (int i = 0; i < n; i++) {
//如果再同一行表示重复。 根据两点的斜率来判断是否处在同一斜线上(y2-y1)==(x2-x2)相等表示斜率为1 处在同一个斜线上。所以该位置不能放在棋子,返回false
if (arr[n] == arr[i] || Math.abs(n - i) == Math.abs(arr[n] - arr[i])) {
return false;
}
}
return true;
}
//打印结果
private void print(){
for (int i : arr) {
System.out.print(i);
}
System.out.println();
}
}