一、八皇后问题描述
八皇后问题,是一一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯.贝瑟尔于1848年提出 : 在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一-列或同-斜线上,问有多少种摆法。
二、八皇后问题思路分析 (使用到回溯算法)
(1)、第一个皇后先放第一行第- -列
(2)、第二个皇后放在第二行第一列、然后判断是否0K,如果不0K, 继续放在第二列、第三列、依次把所有列都放完,找到一个合适的位置
(3)、继续第三个皇后,还是第一列、第二列…直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解。
(4)、当得到一个正确解时,在栈回退到上一一个栈时,就会开始回溯,即将第一个皇后,放到第一-列的所有正确解,全部得到。
(5)、然后回头继续第一个皇后放第二列,后面继续循环执行1,2,3的步骤。
说明:本来应该创建一-个二维数组来表示棋盘,但是实际上可以通过算法,用一个一维数组即可解决问题。
比如:arr = {0,4,7,5,2,6,1,3}:
①数组下标+1:表示行的位置
②数组元素+1:表示列的位置
比如0:第一行第一列 4:第二行第五列
三、代码实现
package com.ycx.recursion;
import java.util.Queue;
public class Queue8 {
//定义一个max:表示共有多少个皇后
int max = 8;
/*
定义一个数组:表示保存皇后位置的结果
比如:arr = {0,4,7,5,2,6,1,3}
数组下标+1:表示行的位置
数组元素+1:表示列的位置 比如0:第一行第一列 4:第二行第五列
*/
int[] arr = new int[max];
static int count = 0;
static int judgecount=0;
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
queue8.check(0); //放到第一列
System.out.printf("一共有%d解法",count);
System.out.println();
System.out.printf("一共有判断冲突的次数%d次",judgecount);
}
//编写一个方法:check是每一次递归时,进入到check中都有for (int i = 0; i < max ; i++) 所以会有回溯
private void check(int n){
if(n==max){ //表示8个皇后全部放完 int[] arr = new int[max] 是从0开始的 max=8表示第九个皇后
print();
return;
}
//依次放入皇后 并判断是否冲突
for (int i = 0; i < max ; i++) {
//先把当前这个皇后n放入该行第一列
arr[n] = i; //i=0 从第一列开始
//判断当前位置第n个皇后到第i列时,是否冲突
if(judege(n)){ //表示不冲突
check(n+1);//递归回溯 放第n+1个皇后
}
//如果冲突 返回到最前面 执行arr[n]=i; (i++)皇后后移一列
}
}
/*
判断是否冲突(第n个皇后与前面n-1个皇后是否冲突):
①是否行相同
②是否列相同
③是否在同一斜线上
*/
private boolean judege(int n){
judgecount++;
for (int i = 0; i < n ; i++) {
/*
arr[i] == arr[n]:判断是否在同一列
Math.abs(i-n)==Math.abs(arr[i]-arr[n]):判断是否在同一斜线上(斜率=1,相当于在y=x这条直线上)
*/
if(arr[i] == arr[n] || Math.abs(i-n)==Math.abs(arr[i]-arr[n])){
return false;
}
}
return true;
}
//写一个方法:可以将皇后摆放的位置输出
private void print(){
count++;
for (int i = 0; i <arr.length ; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
四、实验结果
实验结果解释说明:
来源:CSDN
作者:ouuxxxi
链接:https://blog.csdn.net/m0_45097186/article/details/104757901