• 09.递归、递归回溯--迷宫问题、八皇后问题


    
    /**
     * 递归规则:
     * - 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
     * - 方法的局部变量是独立的,不会相互影响, 比如n变量如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.
     * - 递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError)
     * - 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
     */
    public class Factorial {
        //阶乘
        public static int factorial(int n) {
            if (n == 1) {
                return 1;
            } else {
                return factorial(n - 1) * n;
            }
        }
    
        //递归打印
        public static void test(int n) {
            if (n > 2) {
                test(n - 1);
            }
            System.out.println("n=" + n);
        }
    
        public static void main(String[] args) {
            test(4);
            //n=2
            //n=3
            //n=4
            System.out.println("factorial(2) = " + factorial(2));
        }
    }
    
    package stu;
    
    /**
     * 递归回溯--迷宫问题
     */
    public class MiGong {
        /**
         * 地图,1表示墙,0表示该点没走过
         * 走迷宫方法下->右->上->左
         */
        public static int[][] getMap(){
            int[][] map = new int[8][7];
            int row = map.length;//行数
            int col = map[0].length;//列数
            for (int i = 0; i < row; i++) {
                map[i][0] = 1;
                map[i][col-1] = 1;
            }
            for (int i = 0; i < col; i++) {
                map[0][i] = 1;
                map[row-1][i] = 1;
            }
            return map;
        }
        public static void showMap(int[][] map){
            System.out.println("------map-----");
            int row = map.length;
            int col = map[0].length;
            //打印行号
            for (int i = 0; i < col; i++) {
                if (i==0){
                    System.out.print("	"+i+"	");
                } else{
                    System.out.print(i+"	");
                }
            }
            System.out.println();
            for (int i = 0; i < row; i++) {
                //打印列号
                System.out.print(i+"	");
                for (int j = 0; j < col; j++) {
                    System.out.print(console(map[i][j])+"	");
                }
                System.out.println();
            }
            System.out.println("--------------");
        }
        public static String console(int i) {
            if (i == 0) {//未走的点
                return "○";
            } else if (i == 1) {//墙
                return "♟";
            } else if (i == 2) {//已走的点
                return "☻";
            } else if (i == 3) {//死路
                return "×";
            }
            return "×";
        }
        /**
         * 寻路 终点[6][5]
         * 2表示通路走过,3表示该点走过又一次走,变死路了,走不通
         * @param map
         * @param i 横
         * @param j 枞
         * @return
         */
        public static boolean setWay(int[][] map,int i,int j){
            if (map[6][5]==2){
                return true;
            }else {
                if (map[i][j]==0){
                    map[i][j]=2;
                    if (setWay(map,i+1,j)){//向下
                        return true;
                    }else if (setWay(map,i,j+1)){//向右
                        return true;
                    }else if (setWay(map,i-1,j)){//向上
                        return true;
                    }else if (setWay(map,i,j-1)){//向左
                        return true;
                    }else {
                        map[i][j]=3;
                        return false;
                    }
                }else { //遇到墙,或死路,或已经走过
                    return false;
                }
            }
        }
        public static void main(String[] args){
            int[][] map = getMap();
            showMap(map);
            //从[1][1]做起点
            setWay(map,1,1);
            showMap(map);
            //	0	1	2	3	4	5	6
            //0	♟	♟	♟	♟	♟	♟	♟
            //1	♟	☻	○	○	○	○	♟
            //2	♟	☻	○	○	○	○	♟
            //3	♟	☻	○	○	○	○	♟
            //4	♟	☻	○	○	○	○	♟
            //5	♟	☻	○	○	○	○	♟
            //6	♟	☻	☻	☻	☻	☻	♟
            //7	♟	♟	♟	♟	♟	♟	♟
        }
    }
    
    package stu;
    
    /**
     * 八皇后问题:
     * 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,
     * 即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
     * 八皇后问题算法思路分析:
     * 1.第一个皇后先放第一行第一列
     * 2.第二个皇后放在第二行第一列、然后判断是否OK, 如果不OK,继续放在第二列、第三列、依次把所有列都放完,找到一个合适
     * 3.继续第三个皇后,还是第一列、第二列……直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解
     * 4.当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到.
     * 5.然后回头继续第一个皇后放第二列,后面继续循环执行 1,2,3,4的步骤
     */
    public class Queens8 {
        private int MAX = 8;
        private static int count = 0;
        private static int judgeCount = 0;
        //第0行的列的位置,默认【0,0】
        private int firstCol = 0;
        //对应arr下标表示第几行,即第几个皇后
        //arr[i] = val , val 表示第i个皇后,放在第i行的第val列,皇后从0到7共8个,行与列也是从0开始
        int[] arr = new int[MAX];
    
        private boolean queens8 = false;
        private boolean queens82 = false;
    
        public Queens8() {
            queens8 = true;
            new Queens().check(0);
        }
    
        public Queens8(int firstCol) {
            queens82 = true;
            this.firstCol = firstCol;
            new Queens().checkByFirstCol(0);
        }
    
        private class Queens {
            //第n个皇后
            private void check(int n) {
                //1种方法输出一次
                if (n == MAX) {
                    console();
                    return;
                }
                for (int i = 0; i < MAX; i++) {
                    arr[n] = i;
                    if (judge(n)) {
                        check(n + 1);
                    }
                }
            }
    
            //按照第n个皇后在第0行的列的位置
            private void checkByFirstCol(int n) {
                //1种方法输出一次
                if (n == MAX) {
                    console();
                    return;
                }
                for (int i = 0; i < MAX; i++) {
                    if (n == 0 && i > firstCol) {
                        break;
                    }
                    if (n == 0 && i != firstCol) {
                        continue;
                    }
                    arr[n] = i;
                    if (judge(n)) {
                        check(n + 1);
                    }
                }
            }
    
            //判断是否冲突
            //第n个皇后
            private boolean judge(int n) {
                judgeCount++;
                for (int i = 0; i < n; i++) {
                    //第n个是否与前面的n-1在同一列
                    //第n个是否与第i个是否在同一斜线(两个的行差等于列差)
                    if (arr[n] == arr[i] || Math.abs(n - i) == Math.abs(arr[n] - arr[i])) {
                        return false;
                    }
                }
                return true;
            }
        }
    
        //输出位置
        private void console() {
            count++;
            for (int i : arr) {
                System.out.print(i + "	");
            }
            System.out.println();
        }
    
        private void print() {
            if (queens8){
                System.out.println("共有" + count + "种解法");
            }else {
                System.out.println("第0列的皇后放在第"+firstCol+"列,有" + count + "种解法");
            }
            System.out.println("判断冲突次数:" + judgeCount);
        }
    
        public static void main(String[] args) {
            new Queens8().print();
            new Queens8(0).print();
            new Queens8(1).print();
        }
        //0	4	7	5	2	6	1	3	
        //0	5	7	2	6	3	1	4	
        //0	6	3	5	7	1	4	2	
        //0	6	4	7	1	3	5	2	
        //1	3	5	7	2	0	6	4	
        //1	4	6	0	2	7	5	3	
        //1	4	6	3	0	7	5	2	
        //1	5	0	6	3	7	2	4	
        //1	5	7	2	0	3	6	4	
        //1	6	2	5	7	4	0	3	
        //1	6	4	7	0	3	5	2	
        //1	7	5	0	2	4	6	3	
        //2	0	6	4	7	1	3	5	
        //2	4	1	7	0	6	3	5	
        //2	4	1	7	5	3	6	0	
        //2	4	6	0	3	1	7	5	
        //2	4	7	3	0	6	1	5	
        //2	5	1	4	7	0	6	3	
        //2	5	1	6	0	3	7	4	
        //2	5	1	6	4	0	7	3	
        //2	5	3	0	7	4	6	1	
        //2	5	3	1	7	4	6	0	
        //2	5	7	0	3	6	4	1	
        //2	5	7	0	4	6	1	3	
        //2	5	7	1	3	0	6	4	
        //2	6	1	7	4	0	3	5	
        //2	6	1	7	5	3	0	4	
        //2	7	3	6	0	5	1	4	
        //3	0	4	7	1	6	2	5	
        //3	0	4	7	5	2	6	1	
        //3	1	4	7	5	0	2	6	
        //3	1	6	2	5	7	0	4	
        //3	1	6	2	5	7	4	0	
        //3	1	6	4	0	7	5	2	
        //3	1	7	4	6	0	2	5	
        //3	1	7	5	0	2	4	6	
        //3	5	0	4	1	7	2	6	
        //3	5	7	1	6	0	2	4	
        //3	5	7	2	0	6	4	1	
        //3	6	0	7	4	1	5	2	
        //3	6	2	7	1	4	0	5	
        //3	6	4	1	5	0	2	7	
        //3	6	4	2	0	5	7	1	
        //3	7	0	2	5	1	6	4	
        //3	7	0	4	6	1	5	2	
        //3	7	4	2	0	6	1	5	
        //4	0	3	5	7	1	6	2	
        //4	0	7	3	1	6	2	5	
        //4	0	7	5	2	6	1	3	
        //4	1	3	5	7	2	0	6	
        //4	1	3	6	2	7	5	0	
        //4	1	5	0	6	3	7	2	
        //4	1	7	0	3	6	2	5	
        //4	2	0	5	7	1	3	6	
        //4	2	0	6	1	7	5	3	
        //4	2	7	3	6	0	5	1	
        //4	6	0	2	7	5	3	1	
        //4	6	0	3	1	7	5	2	
        //4	6	1	3	7	0	2	5	
        //4	6	1	5	2	0	3	7	
        //4	6	1	5	2	0	7	3	
        //4	6	3	0	2	7	5	1	
        //4	7	3	0	2	5	1	6	
        //4	7	3	0	6	1	5	2	
        //5	0	4	1	7	2	6	3	
        //5	1	6	0	2	4	7	3	
        //5	1	6	0	3	7	4	2	
        //5	2	0	6	4	7	1	3	
        //5	2	0	7	3	1	6	4	
        //5	2	0	7	4	1	3	6	
        //5	2	4	6	0	3	1	7	
        //5	2	4	7	0	3	1	6	
        //5	2	6	1	3	7	0	4	
        //5	2	6	1	7	4	0	3	
        //5	2	6	3	0	7	1	4	
        //5	3	0	4	7	1	6	2	
        //5	3	1	7	4	6	0	2	
        //5	3	6	0	2	4	1	7	
        //5	3	6	0	7	1	4	2	
        //5	7	1	3	0	6	4	2	
        //6	0	2	7	5	3	1	4	
        //6	1	3	0	7	4	2	5	
        //6	1	5	2	0	3	7	4	
        //6	2	0	5	7	4	1	3	
        //6	2	7	1	4	0	5	3	
        //6	3	1	4	7	0	2	5	
        //6	3	1	7	5	0	2	4	
        //6	4	2	0	5	7	1	3	
        //7	1	3	0	6	4	2	5	
        //7	1	4	2	0	6	3	5	
        //7	2	0	5	1	4	6	3	
        //7	3	0	2	5	1	6	4	
        //共有92种解法
        //判断冲突次数:15720
        //0	4	7	5	2	6	1	3	
        //0	5	7	2	6	3	1	4	
        //0	6	3	5	7	1	4	2	
        //0	6	4	7	1	3	5	2	
        //第0列的皇后放在第0列,有96种解法
        //判断冲突次数:17505
        //1	3	5	7	2	0	6	4	
        //1	4	6	0	2	7	5	3	
        //1	4	6	3	0	7	5	2	
        //1	5	0	6	3	7	2	4	
        //1	5	7	2	0	3	6	4	
        //1	6	2	5	7	4	0	3	
        //1	6	4	7	0	3	5	2	
        //1	7	5	0	2	4	6	3	
        //第0列的皇后放在第1列,有104种解法
        //判断冲突次数:19562
    }
    
  • 相关阅读:
    js某一时间加上指定时长
    .net mvc后端传值与前端js交互
    js里面的引用传递(数组赋值)
    datagrid的一些常见用法
    计算页面高度
    easyui datagrid导出
    导出highcharts图表到Csv(Xls)
    导出highcharts图表到pdf
    js导出table(简单粗暴)
    47.Permutations II
  • 原文地址:https://www.cnblogs.com/fly-book/p/11648642.html
Copyright © 2020-2023  润新知