递归和回溯求解8皇后问题

SystemArchitect 2020-06-02

目录

递归和回溯

递归原理

(1)什么是递归?
答:递归就是自己调用自己,每次调用都传入不同的变量
(2)递归调用的机制
答:栈。当程序执行到一个方法的时候,为该方法开辟一个独立的栈空间用于存放该方法所用到的全部变量,如果这些变量是引用变量,那么他们则是共享一个变量空间,其他的变量有独立的空间。
(3)使用递归的重要规则

  • 终止条件
  • 递归调用过程中逐渐向终止条件趋近,否者是死递归

回溯原理

(1)什么是回溯?
答:简单来讲就是:当前的操作不符合要求时,则退回到到上一步,重新规划当前操作的方法。

递归和回溯算法的经典应用场景

8皇后问题
问题描述: 在8*8的棋盘上摆放8个皇后,要求:所有的皇后均不能在同一行、同一列和斜对角上,求所有的摆法?
分析: 8皇后问题综合应用了递归调用和回溯的思想,逐一摆放第1个皇后一直到第8个皇后,每次摆放一个皇后的位置时候,需要判断当前皇后的位置是否与之前所有已经摆放的皇后的位置相冲突,如果冲突,则回溯,即重新规划上一个皇后的位置,直到满足条件位置,如果不冲突,则采用递归调用的思想,规划下一个皇后的摆放位置。
解决8皇后问题的几个关键点

  • 什么时候递归?及其递归的终止条件
    (1)递归主要是在当前皇后的摆放位置符合要求时,进行下个一个皇后位置规划时使用递归,当8个皇后都摆放完成时,递归结束
  • 什么时候回溯?进行回溯的条件
    (1)在当前皇后的位置摆放不符合要求时,进行回溯,更换当前皇后的位置,直到符合要求

8皇后问题的Java代码实现

/**
 * 8皇后问题:
 * 8*8的棋盘上,放置8个皇后,要求8个皇后不能再同一行同一列和同一对对角线上
 * 求出所有的摆法
 */
public class Queue8 {

    private int[] array=new int[8];//表示8*8的棋盘,array[n]==i;每个皇后放一行,第n个皇后即第n行,放置在第i列
    private int count=0;//记录总的结果数量
    public static void main(String[] args) {
        Queue8 queue8=new Queue8();
        queue8.check(0);//从第一个皇后开始递归
        System.out.print( queue8.count);
    }
    /**
     * 摆放第n个皇后
     * @param n
     */
    private  void check(int n){
        //使用递归求解:
        //递归的结束条件:n==8时,此时[0,7]个皇后已经摆放完成。
        if(n==8){
            print();//打印每一种结果
            return;//结束次此方法
        }
        //开始递归和回溯
        //递归发生在:不产生冲突的情况下:check(n+1);
        //回溯发生在:产生了冲突:则当前的check(n)不成立;重现摆放至下一个位置;
        for(int i=0;i<8;i++){
            array[n]=i;//尝试将第n个皇后摆放在第i列;
            if(judge(n)){//和第n个皇后之前的所有皇后比较,判断当前位置是否合法
                //如果合法,进入递归调用,开始安排第n+1个皇后的位置
                check(n+1);
            }
            //否则的话,进入回溯环节,重新安排第n个皇后的位置即array[n]=i+1;
        }
    }
    /**
     * 判断该皇后放置的位置是否合法
     */
    private boolean judge(int n){
        //不在同一行约束,采用array[]数组一定不再同一行
        //不同同一列:array[n1]!=array[n2];
        //不在同一对角线上array[n1]-array[n2]!=n1-n2,斜率不为1或者-1

        //当前的皇后和之前的所有皇后均要比较,只有全部符合才为true
        for(int i=0;i<n;i++){
            if(array[n]==array[i] || Math.abs(array[i]-array[n])==Math.abs(i-n)){
                return false;
            }
        }
        return true;
    }

    /**
     * 打印摆放的结果
     */
    private void print(){
        count++;
        for(int i=0;i<8;i++){
            System.out.print(array[i]+" ");
        }
        System.out.println();//每一种结果换行
    }
}

相关推荐