【Java数据结构+算法】递归-----八皇后问题(分析与实现)

陌路散爱 提交于 2020-03-10 07:53:52

一、八皇后问题描述

八皇后问题,是一一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯.贝瑟尔于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();
    }


}

四、实验结果

实验结果解释说明:
在这里插入图片描述
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!