递归解决迷宫问题和八皇后问题(Java)

递归

递归的基本概念

简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。

递归调用机制图解

图解栈调用

递归需要遵守的重要原则

  • 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)。
  • 方法的局部变量是独立的,不会相互影响,比如n变量。
  • 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据。
  • 递归必须向退出递归的条件逼近,否则就是无限递归,出现(StackOverflowError,栈溢出错误)
  • 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。

迷宫问题

问题描述

图解

找出一条从入口到出口的路

回溯法实现

package com.athome.recursion;

/**
 * Description:
 * Author:江洋大盗
 * Date:2021/1/22 18:48
 */
public class Maze {
    
    
    public static void main(String[] args) {
    
    
        int[][] map = new int[8][7];
        for (int i = 0; i < 8; i++) {
    
    
            map[i][0] = 1;
            map[i][6] = 1;
        }
        for (int i = 0; i < 7; i++) {
    
    
            map[0][i] = 1;
            map[7][i] = 1;
        }
        for (int i = 0; i < 5; i++) {
    
    
            map[3][i] = 1;
        }
        for (int i = 5; i > 1; i--) {
    
    
            map[5][i] = 1;
        }
        findWay(map, 1, 1);
        //输出map
        for (int i = 0; i < 8; i++) {
    
    
            for (int j = 0; j < 7; j++) {
    
    
                System.out.print(map[i][j] + "\t");
            }
            System.out.println();
        }
    }

    /**
     * 探索思路:下-右-上-左
     * 0:表示没有探索过的地方
     * 1:表示墙
     * 2:表示可以走通的路
     * 3:表示走不通的路
     *
     * @param map 表示迷宫的数组
     * @param i   起始坐标
     * @param j   起始坐标
     * @return 返回是否找到正确的路
     */
    public static boolean findWay(int[][] map, int i, int j) {
    
    
        //代表正确找到了终点,递归结束
        if (map[6][5] == 2) {
    
    
            return true;
        } else {
    
    
            //表示还没有探索过的地方
            if (map[i][j] == 0) {
    
    
                //先假设可以走通
                map[i][j] = 2;
                if (findWay(map, i + 1, j)) {
    
    
                    return true;
                } else if (findWay(map, i, j + 1)) {
    
    
                    return true;
                } else if (findWay(map, i - 1, j)) {
    
    
                    return true;
                } else if (findWay(map, i, j - 1)) {
    
    
                    return true;
                } else {
    
    
                    map[i][j] = 3;
                    return false;
                }
            } else {
    
    
                return false;
            }
        }
    }
}

八皇后问题

问题介绍

在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。

代码实现

package com.atschool.recursion;


/**
 * Description:
 * Author:江洋大盗
 * Date:2021/1/22 19:15
 */
public class Queen8 {
    
    
    static int maxSize = 8;//表示棋盘的大小
    static int[] solution = new int[maxSize];//存放每一种解法
    static int count = 0;//记录有多少种解法
    static int judgeNum = 0;//记录一共判断多少次

    /**
     * 输出方法
     */
    public static void print() {
    
    
        count++;
        for (int i : solution) {
    
    
            System.out.print(i + "\t");
        }
        System.out.println();
    }

    /**
     * 判断当前位置是否可以落棋
     *
     * @param n 表示当前棋子位置
     * @return 若当前位置可行,返回true,否则返回false
     */
    public static boolean judge(int n) {
    
    
        judgeNum++;
        for (int i = 0; i < n; i++) {
    
    
            if (solution[i] == solution[n] ||
                    Math.abs(n - i) == Math.abs(solution[n] - solution[i])) {
    
    
                return false;
            }
        }
        return true;
    }

    /**
     * @param n 第n个皇后
     */
    public static void check(int n) {
    
    
        //限定结束条件
        if (n == maxSize) {
    
    
            print();
            return;
        }
        for (int i = 0; i < maxSize; i++) {
    
    
            //先把当前皇后n,放到该行的第i列
            solution[n] = i;
            //判断该位置是否可行
            if (judge(n)) {
    
    
                //如果可行就放下一个皇后
                check(n + 1);
            }
            //如果冲突就继续放置该皇后,放置位置后移一个
        }
    }

    public static void main(String[] args) {
    
    
        check(0);
        System.out.println("共有" + count + "种解法.");
        System.out.println("共判断了" + judgeNum + "次.");
    }
}


结语

只要能收获甜蜜,荆棘丛中也有蜜蜂忙碌的身影,未来的你一定会感谢现在努力的自己。

猜你喜欢

转载自blog.csdn.net/m0_52099927/article/details/112999676