算法:用Java递归回溯求解八皇后问题的所有解(共92种解)

八皇后问题,就是国际象棋上面的皇后,可以横竖斜地走,很威风。国际象棋棋盘是8*8的,上面需要放8个皇后,这8个皇后无论横纵斜,都无法攻击到其他的皇后,这样就是一个八皇后问题的解。今天我们就用Java来实现八皇后问题的所有解:

import java.util.HashSet;
import java.util.Set;

/**
 * @author LiYang
 * @ClassName EightQueens
 * @Description 八皇后问题的解决实现类
 * @date 2019/12/26 10:11
 */
public class EightQueens {

    /**
     * 检测纵向的皇后是否符合条件
     * @param queen 皇后排列的位置
     * @param level 当前遍历到的行
     * @return 纵向是否满足条件
     */
    private static boolean isVerticalCorrect(int[] queen, int level) {
        //皇后横向位置的集合
        Set<Integer> position = new HashSet<>();

        //将已遍历行的皇后位置放入集合
        for (int i = 0; i < level; i++) {
            position.add(queen[i]);
        }

        //如果位置各不相同,则集合有当前行的项数,返回true
        //如果集合没有当前行的项数,则竖直方向有重复,返回false
        return position.size() == level;
    }

    /**
     * 检测斜线的皇后是否符合条件
     * @param queen 皇后排列的位置
     * @param level 当前遍历到的行
     * @return 斜线是否满足条件
     */
    private static boolean isObliqueCorrect(int[] queen, int level) {
        //已有的每一行逐行验证
        for (int i = 0; i < level; i++) {

            //得到当前行的皇后位置
            int position = queen[i];

            //左偏移值
            int leftOffset = 0;

            //从当前数组的位置开始往左遍历
            for (int left = i; left > 0; left--) {

                //左偏移值自增
                leftOffset ++;

                //如果左偏移未越界,且左边行的皇后位置与当前皇后位置斜线重合
                if (i - leftOffset >= 0
                        && (position - leftOffset == queen[i - leftOffset]
                        || position + leftOffset == queen[i - leftOffset])) {

                    //则不符合条件
                    return false;
                }
            }

            //右偏移值
            int rightOffset = 0;

            //从当前数组的位置开始往右遍历
            for (int right = i; right < level; right++) {

                //右偏移值自增
                rightOffset ++;

                //如果右偏移未超过当前行,且右边行的皇后位置与当前皇后位置斜线重合
                if (i + rightOffset < level
                        && (position - rightOffset == queen[i + rightOffset]
                        || position + rightOffset == queen[i + rightOffset])) {

                    //则不符合条件
                    return false;
                }
            }
        }

        //经过了检测,斜线上符合条件
        return true;
    }

    /**
     * 检测当前的皇后排列是否满足条件
     * @param queen 皇后排列的位置
     * @param level 当前遍历到的行
     * @return 斜线是否满足条件
     */
    private static boolean isCorrect(int[] queen, int level) {
        //先检验纵向是否重复(横向必然只有一个)
        boolean vertical = isVerticalCorrect(queen, level);

        //纵向不符合,直接返回不符合
        if (!vertical) {
            return false;
        }

        //再检验对角线是否重复
        boolean oblique = isObliqueCorrect(queen, level);

        //斜线不符合,直接返回不符合
        if (!oblique) {
            return false;
        }

        //通过检验后,返回正确
        return true;
    }

    /**
     * 深拷贝数组
     * @param arr 待拷贝的数组
     * @return 拷贝的数组副本
     */
    private static int[] copyArr(int[] arr) {
        //新建数组
        int[] newArr = new int[arr.length];

        //逐一拷贝
        for (int i = 0; i < arr.length; i++) {
            newArr[i] = arr[i];
        }

        //返回拷贝好的数组副本
        return newArr;
    }

    /**
     * 八皇后算法的方法
     * @param queen 当前的皇后排列
     * @param level 当前要遍历的行
     */
    private static void eightQueens(int[] queen, int level) {
        //如果当前的皇后排列状态不满足条件
        if (!isCorrect(queen, level)) {
            
            //结束当前递归分支,递归回溯到上一步
            return;
        }
        
        //如果已经所有行都遍历完了,且经过了上面的检验
        if (level == 8) {

            //打印求得的八皇后解
            printEightQueens(queen);

            //结束当前递归分支
            return;
        }

        //当前行的8个位置遍历
        for (int i = 0; i < 8; i++) {

            //当前行8个位置都试一下
            queen[level] = i;

            //递归尝试下一行的8个位置
            eightQueens(copyArr(queen), level + 1);
        }
    }

    /**
     * 根据最终得到的皇后排列,打印出答案
     * @param queen 满足条件的皇后排列
     */
    private static void printEightQueens(int[] queen) {
        //打印每一行的皇后棋盘
        for (int i = 0; i < queen.length; i++) {

            //根据皇后位置来打印每一行棋盘
            switch (queen[i]) {
                case 0: System.out.println("皇十十十十十十十"); break;
                case 1: System.out.println("十皇十十十十十十"); break;
                case 2: System.out.println("十十皇十十十十十"); break;
                case 3: System.out.println("十十十皇十十十十"); break;
                case 4: System.out.println("十十十十皇十十十"); break;
                case 5: System.out.println("十十十十十皇十十"); break;
                case 6: System.out.println("十十十十十十皇十"); break;
                case 7: System.out.println("十十十十十十十皇"); break;
            }
        }

        //打印空行,隔开答案
        System.out.println();
    }

    /**
     * 八皇后算法的驱动方法
     */
    public static void eightQueens() {
        //皇后的初始排列数组,都在左边第一位
        int[] queen = new int[8];

        //从第一行开始
        int level = 0;

        //调用八皇后算法的递归方法
        eightQueens(queen, level);
    }

    /**
     * 运行八皇后求解算法,共92个解
     * 注意:本算法运用的是递归回溯法,就是递归先往深处走,如果
     * 已经不符合规则了,就回退一步,然后上一步再继续往右遍历并
     * 递归,直到找到符合规定的答案。这种回溯法,比起穷举法,可
     * 以减少大量的无效皇后排列,时间复杂度也会低于穷举法
     * @param args
     */
    public static void main(String[] args) {
        //调用八皇后算法的方法,控制台得出答案
        eightQueens();
    }

}

运行EightQueens类的main方法,控制台输出了八皇后问题的92个解,本算法测试通过:

皇十十十十十十十
十十十十皇十十十
十十十十十十十皇
十十十十十皇十十
十十皇十十十十十
十十十十十十皇十
十皇十十十十十十
十十十皇十十十十

皇十十十十十十十
十十十十十皇十十
十十十十十十十皇
十十皇十十十十十
十十十十十十皇十
十十十皇十十十十
十皇十十十十十十
十十十十皇十十十

皇十十十十十十十
十十十十十十皇十
十十十皇十十十十
十十十十十皇十十
十十十十十十十皇
十皇十十十十十十
十十十十皇十十十
十十皇十十十十十

皇十十十十十十十
十十十十十十皇十
十十十十皇十十十
十十十十十十十皇
十皇十十十十十十
十十十皇十十十十
十十十十十皇十十
十十皇十十十十十

十皇十十十十十十
十十十皇十十十十
十十十十十皇十十
十十十十十十十皇
十十皇十十十十十
皇十十十十十十十
十十十十十十皇十
十十十十皇十十十

十皇十十十十十十
十十十十皇十十十
十十十十十十皇十
皇十十十十十十十
十十皇十十十十十
十十十十十十十皇
十十十十十皇十十
十十十皇十十十十

十皇十十十十十十
十十十十皇十十十
十十十十十十皇十
十十十皇十十十十
皇十十十十十十十
十十十十十十十皇
十十十十十皇十十
十十皇十十十十十

十皇十十十十十十
十十十十十皇十十
皇十十十十十十十
十十十十十十皇十
十十十皇十十十十
十十十十十十十皇
十十皇十十十十十
十十十十皇十十十

十皇十十十十十十
十十十十十皇十十
十十十十十十十皇
十十皇十十十十十
皇十十十十十十十
十十十皇十十十十
十十十十十十皇十
十十十十皇十十十

十皇十十十十十十
十十十十十十皇十
十十皇十十十十十
十十十十十皇十十
十十十十十十十皇
十十十十皇十十十
皇十十十十十十十
十十十皇十十十十

十皇十十十十十十
十十十十十十皇十
十十十十皇十十十
十十十十十十十皇
皇十十十十十十十
十十十皇十十十十
十十十十十皇十十
十十皇十十十十十

十皇十十十十十十
十十十十十十十皇
十十十十十皇十十
皇十十十十十十十
十十皇十十十十十
十十十十皇十十十
十十十十十十皇十
十十十皇十十十十

十十皇十十十十十
皇十十十十十十十
十十十十十十皇十
十十十十皇十十十
十十十十十十十皇
十皇十十十十十十
十十十皇十十十十
十十十十十皇十十

十十皇十十十十十
十十十十皇十十十
十皇十十十十十十
十十十十十十十皇
皇十十十十十十十
十十十十十十皇十
十十十皇十十十十
十十十十十皇十十

十十皇十十十十十
十十十十皇十十十
十皇十十十十十十
十十十十十十十皇
十十十十十皇十十
十十十皇十十十十
十十十十十十皇十
皇十十十十十十十

十十皇十十十十十
十十十十皇十十十
十十十十十十皇十
皇十十十十十十十
十十十皇十十十十
十皇十十十十十十
十十十十十十十皇
十十十十十皇十十

十十皇十十十十十
十十十十皇十十十
十十十十十十十皇
十十十皇十十十十
皇十十十十十十十
十十十十十十皇十
十皇十十十十十十
十十十十十皇十十

十十皇十十十十十
十十十十十皇十十
十皇十十十十十十
十十十十皇十十十
十十十十十十十皇
皇十十十十十十十
十十十十十十皇十
十十十皇十十十十

十十皇十十十十十
十十十十十皇十十
十皇十十十十十十
十十十十十十皇十
皇十十十十十十十
十十十皇十十十十
十十十十十十十皇
十十十十皇十十十

十十皇十十十十十
十十十十十皇十十
十皇十十十十十十
十十十十十十皇十
十十十十皇十十十
皇十十十十十十十
十十十十十十十皇
十十十皇十十十十

十十皇十十十十十
十十十十十皇十十
十十十皇十十十十
皇十十十十十十十
十十十十十十十皇
十十十十皇十十十
十十十十十十皇十
十皇十十十十十十

十十皇十十十十十
十十十十十皇十十
十十十皇十十十十
十皇十十十十十十
十十十十十十十皇
十十十十皇十十十
十十十十十十皇十
皇十十十十十十十

十十皇十十十十十
十十十十十皇十十
十十十十十十十皇
皇十十十十十十十
十十十皇十十十十
十十十十十十皇十
十十十十皇十十十
十皇十十十十十十

十十皇十十十十十
十十十十十皇十十
十十十十十十十皇
皇十十十十十十十
十十十十皇十十十
十十十十十十皇十
十皇十十十十十十
十十十皇十十十十

十十皇十十十十十
十十十十十皇十十
十十十十十十十皇
十皇十十十十十十
十十十皇十十十十
皇十十十十十十十
十十十十十十皇十
十十十十皇十十十

十十皇十十十十十
十十十十十十皇十
十皇十十十十十十
十十十十十十十皇
十十十十皇十十十
皇十十十十十十十
十十十皇十十十十
十十十十十皇十十

十十皇十十十十十
十十十十十十皇十
十皇十十十十十十
十十十十十十十皇
十十十十十皇十十
十十十皇十十十十
皇十十十十十十十
十十十十皇十十十

十十皇十十十十十
十十十十十十十皇
十十十皇十十十十
十十十十十十皇十
皇十十十十十十十
十十十十十皇十十
十皇十十十十十十
十十十十皇十十十

十十十皇十十十十
皇十十十十十十十
十十十十皇十十十
十十十十十十十皇
十皇十十十十十十
十十十十十十皇十
十十皇十十十十十
十十十十十皇十十

十十十皇十十十十
皇十十十十十十十
十十十十皇十十十
十十十十十十十皇
十十十十十皇十十
十十皇十十十十十
十十十十十十皇十
十皇十十十十十十

十十十皇十十十十
十皇十十十十十十
十十十十皇十十十
十十十十十十十皇
十十十十十皇十十
皇十十十十十十十
十十皇十十十十十
十十十十十十皇十

十十十皇十十十十
十皇十十十十十十
十十十十十十皇十
十十皇十十十十十
十十十十十皇十十
十十十十十十十皇
皇十十十十十十十
十十十十皇十十十

十十十皇十十十十
十皇十十十十十十
十十十十十十皇十
十十皇十十十十十
十十十十十皇十十
十十十十十十十皇
十十十十皇十十十
皇十十十十十十十

十十十皇十十十十
十皇十十十十十十
十十十十十十皇十
十十十十皇十十十
皇十十十十十十十
十十十十十十十皇
十十十十十皇十十
十十皇十十十十十

十十十皇十十十十
十皇十十十十十十
十十十十十十十皇
十十十十皇十十十
十十十十十十皇十
皇十十十十十十十
十十皇十十十十十
十十十十十皇十十

十十十皇十十十十
十皇十十十十十十
十十十十十十十皇
十十十十十皇十十
皇十十十十十十十
十十皇十十十十十
十十十十皇十十十
十十十十十十皇十

十十十皇十十十十
十十十十十皇十十
皇十十十十十十十
十十十十皇十十十
十皇十十十十十十
十十十十十十十皇
十十皇十十十十十
十十十十十十皇十

十十十皇十十十十
十十十十十皇十十
十十十十十十十皇
十皇十十十十十十
十十十十十十皇十
皇十十十十十十十
十十皇十十十十十
十十十十皇十十十

十十十皇十十十十
十十十十十皇十十
十十十十十十十皇
十十皇十十十十十
皇十十十十十十十
十十十十十十皇十
十十十十皇十十十
十皇十十十十十十

十十十皇十十十十
十十十十十十皇十
皇十十十十十十十
十十十十十十十皇
十十十十皇十十十
十皇十十十十十十
十十十十十皇十十
十十皇十十十十十

十十十皇十十十十
十十十十十十皇十
十十皇十十十十十
十十十十十十十皇
十皇十十十十十十
十十十十皇十十十
皇十十十十十十十
十十十十十皇十十

十十十皇十十十十
十十十十十十皇十
十十十十皇十十十
十皇十十十十十十
十十十十十皇十十
皇十十十十十十十
十十皇十十十十十
十十十十十十十皇

十十十皇十十十十
十十十十十十皇十
十十十十皇十十十
十十皇十十十十十
皇十十十十十十十
十十十十十皇十十
十十十十十十十皇
十皇十十十十十十

十十十皇十十十十
十十十十十十十皇
皇十十十十十十十
十十皇十十十十十
十十十十十皇十十
十皇十十十十十十
十十十十十十皇十
十十十十皇十十十

十十十皇十十十十
十十十十十十十皇
皇十十十十十十十
十十十十皇十十十
十十十十十十皇十
十皇十十十十十十
十十十十十皇十十
十十皇十十十十十

十十十皇十十十十
十十十十十十十皇
十十十十皇十十十
十十皇十十十十十
皇十十十十十十十
十十十十十十皇十
十皇十十十十十十
十十十十十皇十十

十十十十皇十十十
皇十十十十十十十
十十十皇十十十十
十十十十十皇十十
十十十十十十十皇
十皇十十十十十十
十十十十十十皇十
十十皇十十十十十

十十十十皇十十十
皇十十十十十十十
十十十十十十十皇
十十十皇十十十十
十皇十十十十十十
十十十十十十皇十
十十皇十十十十十
十十十十十皇十十

十十十十皇十十十
皇十十十十十十十
十十十十十十十皇
十十十十十皇十十
十十皇十十十十十
十十十十十十皇十
十皇十十十十十十
十十十皇十十十十

十十十十皇十十十
十皇十十十十十十
十十十皇十十十十
十十十十十皇十十
十十十十十十十皇
十十皇十十十十十
皇十十十十十十十
十十十十十十皇十

十十十十皇十十十
十皇十十十十十十
十十十皇十十十十
十十十十十十皇十
十十皇十十十十十
十十十十十十十皇
十十十十十皇十十
皇十十十十十十十

十十十十皇十十十
十皇十十十十十十
十十十十十皇十十
皇十十十十十十十
十十十十十十皇十
十十十皇十十十十
十十十十十十十皇
十十皇十十十十十

十十十十皇十十十
十皇十十十十十十
十十十十十十十皇
皇十十十十十十十
十十十皇十十十十
十十十十十十皇十
十十皇十十十十十
十十十十十皇十十

十十十十皇十十十
十十皇十十十十十
皇十十十十十十十
十十十十十皇十十
十十十十十十十皇
十皇十十十十十十
十十十皇十十十十
十十十十十十皇十

十十十十皇十十十
十十皇十十十十十
皇十十十十十十十
十十十十十十皇十
十皇十十十十十十
十十十十十十十皇
十十十十十皇十十
十十十皇十十十十

十十十十皇十十十
十十皇十十十十十
十十十十十十十皇
十十十皇十十十十
十十十十十十皇十
皇十十十十十十十
十十十十十皇十十
十皇十十十十十十

十十十十皇十十十
十十十十十十皇十
皇十十十十十十十
十十皇十十十十十
十十十十十十十皇
十十十十十皇十十
十十十皇十十十十
十皇十十十十十十

十十十十皇十十十
十十十十十十皇十
皇十十十十十十十
十十十皇十十十十
十皇十十十十十十
十十十十十十十皇
十十十十十皇十十
十十皇十十十十十

十十十十皇十十十
十十十十十十皇十
十皇十十十十十十
十十十皇十十十十
十十十十十十十皇
皇十十十十十十十
十十皇十十十十十
十十十十十皇十十

十十十十皇十十十
十十十十十十皇十
十皇十十十十十十
十十十十十皇十十
十十皇十十十十十
皇十十十十十十十
十十十皇十十十十
十十十十十十十皇

十十十十皇十十十
十十十十十十皇十
十皇十十十十十十
十十十十十皇十十
十十皇十十十十十
皇十十十十十十十
十十十十十十十皇
十十十皇十十十十

十十十十皇十十十
十十十十十十皇十
十十十皇十十十十
皇十十十十十十十
十十皇十十十十十
十十十十十十十皇
十十十十十皇十十
十皇十十十十十十

十十十十皇十十十
十十十十十十十皇
十十十皇十十十十
皇十十十十十十十
十十皇十十十十十
十十十十十皇十十
十皇十十十十十十
十十十十十十皇十

十十十十皇十十十
十十十十十十十皇
十十十皇十十十十
皇十十十十十十十
十十十十十十皇十
十皇十十十十十十
十十十十十皇十十
十十皇十十十十十

十十十十十皇十十
皇十十十十十十十
十十十十皇十十十
十皇十十十十十十
十十十十十十十皇
十十皇十十十十十
十十十十十十皇十
十十十皇十十十十

十十十十十皇十十
十皇十十十十十十
十十十十十十皇十
皇十十十十十十十
十十皇十十十十十
十十十十皇十十十
十十十十十十十皇
十十十皇十十十十

十十十十十皇十十
十皇十十十十十十
十十十十十十皇十
皇十十十十十十十
十十十皇十十十十
十十十十十十十皇
十十十十皇十十十
十十皇十十十十十

十十十十十皇十十
十十皇十十十十十
皇十十十十十十十
十十十十十十皇十
十十十十皇十十十
十十十十十十十皇
十皇十十十十十十
十十十皇十十十十

十十十十十皇十十
十十皇十十十十十
皇十十十十十十十
十十十十十十十皇
十十十皇十十十十
十皇十十十十十十
十十十十十十皇十
十十十十皇十十十

十十十十十皇十十
十十皇十十十十十
皇十十十十十十十
十十十十十十十皇
十十十十皇十十十
十皇十十十十十十
十十十皇十十十十
十十十十十十皇十

十十十十十皇十十
十十皇十十十十十
十十十十皇十十十
十十十十十十皇十
皇十十十十十十十
十十十皇十十十十
十皇十十十十十十
十十十十十十十皇

十十十十十皇十十
十十皇十十十十十
十十十十皇十十十
十十十十十十十皇
皇十十十十十十十
十十十皇十十十十
十皇十十十十十十
十十十十十十皇十

十十十十十皇十十
十十皇十十十十十
十十十十十十皇十
十皇十十十十十十
十十十皇十十十十
十十十十十十十皇
皇十十十十十十十
十十十十皇十十十

十十十十十皇十十
十十皇十十十十十
十十十十十十皇十
十皇十十十十十十
十十十十十十十皇
十十十十皇十十十
皇十十十十十十十
十十十皇十十十十

十十十十十皇十十
十十皇十十十十十
十十十十十十皇十
十十十皇十十十十
皇十十十十十十十
十十十十十十十皇
十皇十十十十十十
十十十十皇十十十

十十十十十皇十十
十十十皇十十十十
皇十十十十十十十
十十十十皇十十十
十十十十十十十皇
十皇十十十十十十
十十十十十十皇十
十十皇十十十十十

十十十十十皇十十
十十十皇十十十十
十皇十十十十十十
十十十十十十十皇
十十十十皇十十十
十十十十十十皇十
皇十十十十十十十
十十皇十十十十十

十十十十十皇十十
十十十皇十十十十
十十十十十十皇十
皇十十十十十十十
十十皇十十十十十
十十十十皇十十十
十皇十十十十十十
十十十十十十十皇

十十十十十皇十十
十十十皇十十十十
十十十十十十皇十
皇十十十十十十十
十十十十十十十皇
十皇十十十十十十
十十十十皇十十十
十十皇十十十十十

十十十十十皇十十
十十十十十十十皇
十皇十十十十十十
十十十皇十十十十
皇十十十十十十十
十十十十十十皇十
十十十十皇十十十
十十皇十十十十十

十十十十十十皇十
皇十十十十十十十
十十皇十十十十十
十十十十十十十皇
十十十十十皇十十
十十十皇十十十十
十皇十十十十十十
十十十十皇十十十

十十十十十十皇十
十皇十十十十十十
十十十皇十十十十
皇十十十十十十十
十十十十十十十皇
十十十十皇十十十
十十皇十十十十十
十十十十十皇十十

十十十十十十皇十
十皇十十十十十十
十十十十十皇十十
十十皇十十十十十
皇十十十十十十十
十十十皇十十十十
十十十十十十十皇
十十十十皇十十十

十十十十十十皇十
十十皇十十十十十
皇十十十十十十十
十十十十十皇十十
十十十十十十十皇
十十十十皇十十十
十皇十十十十十十
十十十皇十十十十

十十十十十十皇十
十十皇十十十十十
十十十十十十十皇
十皇十十十十十十
十十十十皇十十十
皇十十十十十十十
十十十十十皇十十
十十十皇十十十十

十十十十十十皇十
十十十皇十十十十
十皇十十十十十十
十十十十皇十十十
十十十十十十十皇
皇十十十十十十十
十十皇十十十十十
十十十十十皇十十

十十十十十十皇十
十十十皇十十十十
十皇十十十十十十
十十十十十十十皇
十十十十十皇十十
皇十十十十十十十
十十皇十十十十十
十十十十皇十十十

十十十十十十皇十
十十十十皇十十十
十十皇十十十十十
皇十十十十十十十
十十十十十皇十十
十十十十十十十皇
十皇十十十十十十
十十十皇十十十十

十十十十十十十皇
十皇十十十十十十
十十十皇十十十十
皇十十十十十十十
十十十十十十皇十
十十十十皇十十十
十十皇十十十十十
十十十十十皇十十

十十十十十十十皇
十皇十十十十十十
十十十十皇十十十
十十皇十十十十十
皇十十十十十十十
十十十十十十皇十
十十十皇十十十十
十十十十十皇十十

十十十十十十十皇
十十皇十十十十十
皇十十十十十十十
十十十十十皇十十
十皇十十十十十十
十十十十皇十十十
十十十十十十皇十
十十十皇十十十十

十十十十十十十皇
十十十皇十十十十
皇十十十十十十十
十十皇十十十十十
十十十十十皇十十
十皇十十十十十十
十十十十十十皇十
十十十十皇十十十

你可能感兴趣的:(算法)