数据结构与算法--第7篇(八皇后&回溯算法)

一,八皇后

1,简介:

八皇后问题: 一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
图示:
在这里插入图片描述

2,分析:

  1. 第一个皇后先放第一行第一列;
  2. 第二个放第二行第一列,判断是否满足条件,如果不满足,放到第二列,第三列…依次把所有列都放完,找到一个合适的;
  3. 继续放第三个皇后,还是第一列,第二列…也放在一个不冲突的位置,走完之后找到一个正确解;
  4. 得到一个正确解之后,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一例的所有正确解全部得到;
  5. 然后回头继续将第一个皇后放到第二列,依次循环执行上面步骤;

理论上创建一个二维数组实现八皇后,但是通过分析可以使用一维数组解决;如上图可用数组arr[8]={2,4,7,3,0,6,1,5}来表示,数组下标表示行-1,对应值表示列-1;

3,八皇后代码实现:

package com.recursion;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/6/15  21:48
 * @Description: 游学网
 * @throws:
 */
public class EightQueen {

    private static final int MAX = 8;
    int[] queenArr = new int[MAX];
    private static int count = 0;

    public static void main(String[] args) {
        EightQueen queen = new EightQueen();
        queen.check(0);
        System.out.println("八皇后问题共有:" + count + "种解法");
    }

    public void check(int n) {
        //8个皇后排完了
        if (n == MAX) {
            print();
            return;
        }
        for (int i = 0; i < MAX; i++) {
            //把皇后放到第n行的第i列
            queenArr[n] = i;
            //摆好判断是否冲突
            if (judge(n)) {
                //不冲突,递归放入
                check(n + 1);
            }

        }
    }


    //判断当前皇后是否存在冲突
    public boolean judge(int n) {
        for (int i = 0; i < n; i++) {
            //queenArr[i]==queenArr[n]表示在同一列
            //Math.abs(n-i)==Math.abs(queenArr[n]-queenArr[i])表示在同一斜线
            if (queenArr[i] == queenArr[n] || Math.abs(n - i) == Math.abs(queenArr[n] - queenArr[i])) {
                return false;
            }
        }
        return true;
    }

    //打印
    public void print() {
        count++;
        for (int i : queenArr) {
            System.out.print(i + " ");
        }
        System.out.println();
    }
}

注: 每次得到一个解法之后都会回溯前面放过的皇后,检查是否有新的解法,最终得到92种解法;

猜你喜欢

转载自blog.csdn.net/weixin_42413454/article/details/92112051