五、递归(java)

这篇博客探讨了如何使用回溯算法解决八皇后问题,这是一个经典的计算机科学问题。文章详细介绍了问题背景,分析了问题的核心思路,并阐述了如何通过判断皇后位置合法性以及实施回溯策略来求解解决方案。
摘要由CSDN通过智能技术生成

1.迷宫问题 

/**
 * @company: 北京动力节点
 * @author:韩国庆
 */
public class MazeApp {

    public static void main(String[] args) {

        int[][] map = new int[8][7];

        /**
         * 设置第一行和最后一行为墙,设置为 1
         */
        for(int i=0;i<7;i++){
            map[0][i] = 1;
            map[7][i] = 1;
        }

        /**
         * 设置第一列和第7列为墙
         */
        for (int i=0;i<8;i++){
            map[i][0] = 1;
            map[i][6] = 1;
        }

        /**
         * 设置障碍墙
         */
        map[3][1] = 1;
        map[3][2] = 1;

        System.out.println("新的迷宫");

        for (int i=0;i<8;i++){
            for (int j=0;j<7;j++){
                System.out.print(map[i][j]+" ");
            }
            System.out.println();
        }


        isRun(map,1,1);


        System.out.println("小球走的过线");
        for (int i=0;i<8;i++){
            for (int j=0;j<7;j++){
                System.out.print(map[i][j]+" ");
            }
            System.out.println();
        }


    }


    /**
     * 1.小球从哪一个位置开始触发,起始位置   1、1
     * 2.map是地图对象
     * 3、最终小球到达了  6、5
     * 4、元素为0时表示该点没有走过,元素为1表示是墙,元素为2时表示通过可以走,当元素3时已经走过了
     * 但是走不通。
     *
     */

    public static boolean isRun(int[][] map,int i,int j){
        if (map[6][5]==2){
            return true;
        }else {
            if (map[i][j]==0){//没有走过该点
                map[i][j] = 2;

                //下,右,上,左
                if (isRun(map,i+1,j)){
                    return true;
                }else if (isRun(map,i,j+1)){
                    return true;
                }else if (isRun(map,i-1,j)){
                    return true;
                }else if (isRun(map,i,j-1)){
                    return true;
                }else {
                    map[i][j] = 3;
                    return false;
                }

            }else {
                return false;
            }


        }

    }

}

 2.八皇后问题

八皇后问题(回溯算法)

一、问题介绍:

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是由国际西洋棋手马克斯 • 贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后不能处于同一行、同一列或同一斜线上,问有多少种摆法。通过计算可以得出共有92种摆法,下面我们就对这个问题进行解决。

二、问题分析

1、通过问题的介绍,我们可以获取一些信息,即:任意两个皇后不能处于同一行、同一列或同一斜线上如图所示

 此图表示在(0,0)完成第一次摆放皇后 ,蓝色实心圆表示皇后。

2、思路分析

首先我们在第一行的第一个位置摆一个皇后,因为任意皇后不能在同一行,所以我们只能在下一行摆皇后,但又必须要满足任意皇后不在同一列和同一斜线,在第二行找到满足条件的格子后摆上皇后,接着又在第三行继续找满足条件的格子、、、依次类推,直到在满足条件的情况下,将8个皇后摆完。值得注意的是,在摆到最后一个的时候,此时摆的皇后可能与前面的某个皇后冲突,这时我们就要回溯,把前一步摆的皇后重新摆,如果如此之后还是不能满足条件,那么就在往前一步、、、、这就是回溯。

解释:在第一次摆放皇后完成后,我们会尝试动(7,3),如果没有合适的,在尝试动(6,1)[动一次这个,第七行会从07动一遍]依次类推,在动(5,6){动一次这个,那么动第六行一遍[第六行一个,第七行一遍]再回到第一行之后,然后第一行在(0,1)在玩一遍。

3、实现

1、首先,我们需要一个数组用于存放结果,这里,选取 一维数组arr[ ] 即可;因为任意两个皇后是不可能存在同一行的情况,所以我们只需记录皇后在棋盘中的列坐标即可。一维数组的第一个值就表示棋盘中第一行皇后的列坐标,第二个值表示棋盘中第二行皇后的列坐标值,所以我们只需要一个一维数组就在足够了,相当于,一维数组的索引表示皇后在棋盘中的横坐标,索引所对应的值表示皇后在棋盘中的列坐标。

2、我们需要写一个方法来判断在摆皇后的过程中,皇后的位置是否违反了所给定的规则:即判断任意两个皇后是否在同一行,同一列或同一斜线。

判断任意两个皇后是否在同一列:前面我们给了一个arr[ ]数组来存放皇后的坐标,那么当 arr[n]==arr[i] (即:列坐标相等)时第n个皇后和第i个皇后处于同一列,违反规则。

判断任意两个皇后是否在同一斜线

①:相邻两行的皇后处于同一斜线位置,如图2,那么其横坐标之差的绝对值等于其列坐标之差的绝对值 即:Math.abs(n - i) == Math.abs(arr[i] - arr[n])【Math.abs(x):x的绝对值】

②:不相邻的皇后处于同一斜线位置,如图3,通过图可以看出,两个皇后的横坐标之差等于 2 ,列坐标之差也等于 2 所以可以得出不相邻的皇后处于同一斜线位置时:Math.abs(n - i) == Math.abs(arr[i] - arr[n])

③:综上所述:任意两个皇后处于同一斜线时满足:其横坐标之差的绝对值等于其列坐标之差的绝对值 即:Math.abs(n - i) == Math.abs(arr[i] - arr[n])【Math.abs(x):x的绝对值】

3、

  1. 有了判断任意两个皇后的位置是否合法的方法之后,还需要一个摆皇后的方法,在摆之前我们需要判断皇后是否摆完了,接着通过一个for循环一个一个的摆,在摆的过程中需判断位置是否合法。

public class  Quuen8 {

    // 八皇后问题,在一个8×8的国际象棋棋盘上摆放8个皇后,摆放需遵守皇后不能处于同一行、同一列、同一斜线上,问有多少种摆法
    int max = 8;//皇后个数
    static  int count = 0;//记录有多少种摆法
    // 初始化一个数组用于存放结果
    /*
     * 这里用一维数组存放数据就可以了,这里一维数组中的值存放的是皇后的列坐标,
     * 因为规定皇后是不能摆放在同一行,所以每一行只有一个皇后 ; 一维数组 arr
     * 的第一个值就是 棋盘第一行皇后的列坐标值,第二个值就是皇后在棋盘第二行的列坐标值
     */
    int[] arr = new int[max];

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Quuen8 quuen = new Quuen8();
        quuen.PutQuuen(0);
        System.out.println("共有"+count+"种摆法");
    }

    //写一个摆皇后的方法
    private void PutQuuen(int n) {
        if(n==max) {//因为n是从0开始增加,即n=0表示放第一个皇后,当n==max时表示皇后已经摆完了
            Print();
            return;
        }
        for(int i=0;i<max;i++) {
            arr[n]=i;//放置第一个皇后
            if(judge(n)) {//判断皇后的位置是否冲突,不冲突继续放下一个皇后
                PutQuuen(n+1);
            }
        }
    }


    // 写一个方法,判断皇后在该位置是否会引起冲突,即在同一行或同一列或同一斜线
    private boolean judge(int n) {
        for (int i = 0; i < n; i++) {

            /*
             * 1. 判断 皇后是否在同一列,只需判断皇后的列坐标是否相等即可,即arr[i] == arr[n]
             * 2.判断皇后是否在同一斜线上,只需判断两个皇后的列坐标之差的绝对值与其横坐标之差的绝对值是否相等即可,
             *   即Math.abs(n - i) == Math.abs(arr[i] - arr[n])
             *  */
            if (arr[i] == arr[n] || Math.abs(n - i) == Math.abs(arr[i] - arr[n])) {
                return false;//违反了规则,返回false
            }
        }
        return true;
    }

    //输出
    private void Print() {
        // TODO Auto-generated method stub
        for(int i=0;i<arr.length;i++) {
            System.out.print(arr[i] + " ");
        }
        count++;
        System.out.println();
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值