数据结构和算法——递归处理八皇后问题

一、问题描述

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法(92)。

img

二、解题思路

  1. 第一个皇后先放第一行第一列
  2. 第二个皇后从第二行第一列开始判断是否可行,不可行放在第二列、第三列以此类推......
  3. 继续第三个皇后,还是第一列、第二列……直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解
  4. 当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到
  5. 然后回头继续第一个皇后放第二列,后面继续循环执行1、2、3、4的步骤

三、实现思路

  • 先创建一个值表示到底有多少个皇后;定义一个数组array,用于保存皇后到底保存在哪个位置;(这里不采用二维数组的方式,而是使用一维数组,放置第i行皇后在哪列)
  • 写一个方法,把皇后码放的位置显示出来
  • 写一个方法,放置第n个皇后时,判断该皇后是否位置合法(是否同行、同列、同斜线),判断是否是同一条斜线可以通过判断斜率是否为1来实现
  • 写一个放皇后的方法,从第0个皇后开始放,从第1列开始放,如果冲突就放下一个位置,如果不冲突就继续放下一个,这样递归下去。

四、代码

public class Queens {
    int max = 8; //一共8个皇后,定义初始值
    int[] array = new int[max];
    static int count=0;
    public static void main(String[] args) {
        Queens queens = new Queens();
        queens.put(0);
        System.out.println(count);
    }

    //结果输出方法
    private void print() {
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i]);
        }
        System.out.println();
    }

    //检查放到第n个皇后时,是否与之前的皇后冲突
    private boolean check(int n) {
        for (int i = 0; i < n; i++) {
            if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[i] - array[n])) {
                return false;
            }
        }
        return true;
    }

    //放置第n个皇后
    private void put(int n){
        if (n == max){ //因为下标是从0开始的,所以当n=8时代表再放就是第九个皇后了,就是已经放完了8个。直接打印结果即可。
            count++;
            print();
            return;
        }
        for (int i=0;i<max;i++){
            array[n] = i;//先把这个皇后放到此行的第一个位置
            if (check(n)){//检查放第n个皇后时是否冲突,不冲突的话就继续放置第n+1个。
                put(n+1);
            }
        }//如果冲突了就继续执行 array[n] = i这就相当于这一行的这个位置是不行的,我们要试试下个位置了
    }
}
复制代码

Guess you like

Origin juejin.im/post/7053662503108083726