JAVA data structure 07. Recursive maze problem eight queens problem

JAVA data structure 07. Recursive maze problem eight queens problem

1. Recursive introduction and solution ideas

Recursion : In simple terms, recursion means that the method calls itself, passing in different variables each time it is called.

​ Recursion helps programmers solve complex problems (only need to pay attention to the problems solved by recursion each time), and can make the code concise.

Recursive call rules :

  • When the program executes to a method, it will open up an independent space (stored in the stack);
  • The data (local variables) of each space are independent;
  • Recursion must approach the condition of exiting recursion, otherwise it will be infinite recursion, resulting in a stack overflow error
  • When a method is executed, or when a return is encountered, it will return to the place where the method was called to continue the execution of the following program.

The idea of ​​recursive problem solving : focus on three aspects

  • Find the termination condition of the entire recursion: when should the recursion end?
  • Find the return value: What information should be returned to the upper level recursion?
  • Find a single recursion task: what should this recursion do?

2. Recursive case:

Recursive learning ideas and more cases

2.1 The maze backtracking problem

Scenario : Set up the walls and exits of the maze, looking for a way to escape the maze

Insert picture description here

Description :

/**
* 说明:
*  1. map 表示地图
*  2. i,j 表示从地图的哪个位置开始出发,起始位置(1,1)
*  3. 如果小球能到map[6][5]位置,则说明通路找到
*  4. 当map[i][j] 为0 表示当前位置还没有走过;为1 表示墙;为2 表示通路可以走并且已经走过;为3 表示该点走过并且上下左右四个位置都走不通
*  5. 策略: 方向判断顺序: 下->右->上->左, 如果该点四个位置都走不通,则回溯到上一个点(递归)
*/

Thinking analysis :

  • Find the termination condition of the entire recursion: the ball reaches the exit position [6][5] || Recursively traces back to the initial point and finds nowhere
  • Looking for the return value, what information should be returned to the upper layer? Return to the point whether i, j can go through boolean
  • Find a single recursive task: You need to determine whether the four directions can be passed in the order of the strategy, you can return true, not false

Code implementation :

public class MiGong {
    
    
    public  static void main(String args[]){
    
    
        int[][] map = new int[8][7];
        //初始化迷宫
        setMap(map);
        showMap(map);
        //寻找通路
        setWay(map,1,1);
        showMap(map);
    }
    public static void setMap(int[][] map){
    
    
        //上下两行
        for (int i = 0; i <map[i].length ; i++) {
    
    
            map[0][i] = 1;
            map[7][i] = 1;
        }
        //左右两列
        for (int i = 0; i <map.length ; i++) {
    
    
            map[i][0] = 1;
            map[i][6] = 1;
        }
        //挡板
        map[3][1] = 1;
        map[3][2] = 1;
    }

    public static void showMap(int[][] map){
    
    
        System.out.println("此时的地图情况:");
        for (int[] i:map) {
    
    
            for (int data: i) {
    
    
                System.out.print(data+" ");
            }
            System.out.println();
        }
    }

    /**
     * 说明:
     *  1. map 表示地图
     *  2. i,j 表示从地图的哪个位置开始出发,起始位置(1,1)
     *  3. 如果小球能到map[6][5]位置,则说明通路找到
     *  4. 当map[i][j] 为0 表示当前位置还没有走过;为1 表示墙;为2 表示通路可以走并且已经走过;为3 表示该点走过并且上下左右四个位置都走不通
     *  5. 策略: 方向判断顺序: 下->右->上->左, 如果该点四个位置都走不通,则回溯到上一个点(递归)
     * @param map
     * @param i
     * @param j
     */
    /**
     * 递归解决问题的思路:
     *  1. 找到整个递归的终止条件: 小球到达出口位置[6][5] || 递归回溯到初始点发现走不通
     *  2. 找返回值,应该给上一层返回什么信息? 返回该点i,j 是否能走通  boolean
     *  3. 找到单次递归的任务: 需要按照策略顺序判断四个方向是否可以走通,可以返回true,不可以返回false
     */
    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;  //假定该点是可以走通的,如果无法走通,则回溯时将值改为3
                if(setWay(map,i+1,j)){
    
     //向下走
                    return true;
                }else if(setWay(map,i,j+1)){
    
     //向右走   //elseif 表示 向上走失败后 再向右走
                    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;   //四个方向都走不通,就判断走不通 将该点值变为3
                }
            }else{
    
    
                // map = 1 2 3 时均不走
                return false;
            }
        }
    }
}

Result :

此时的地图情况:
1 1 1 1 1 1 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 1 1 0 0 0 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 1 1 1 1 1 1 
此时的地图情况:
1 1 1 1 1 1 1 
1 2 0 0 0 0 1 
1 2 2 2 0 0 1 
1 1 1 2 0 0 1 
1 0 0 2 0 0 1 
1 0 0 2 0 0 1 
1 0 0 2 2 2 1 
1 1 1 1 1 1 1 

2.2 The Eight Queens Problem

Scenario : Place 8 queens on an 8*8 chess board so that they cannot attack each other: that is, no two queens can be in the same row, the same column, or the same diagonal line, ask how many kinds of placements there are.

Thinking analysis :

  1. The first queen is placed in the first column of the first row;
  2. Put the second queen in the first column of the second row and judge whether it is ok. If it does not meet the rules, continue to put it in the second/third column..., put all the columns in order, and find a suitable one
  3. Continue with the third queen until the eighth queen can be placed in a non-conflicting position, and a correct solution has been found.
  4. If a piece still has no correct solution after trying all 8 positions, the previous pieces are wrong and need to be retrospectively modified; ( Backtracking focus )
  5. When a correct solution is obtained, go back to the previous stack and start backtracking, that is, all correct solutions placed in the first row and first column of the first queen are obtained;
  6. 1 2 3 4 5 After the end of the step, all the solutions that the queen placed in the first row and the first column are obtained, put the first queen in the first row and the second column, and continue to loop through steps 12345 to get all the solutions.

Description :

  • The result obtained is represented by a one-dimensional array , such as: arr=[0,4,7,5,2,6,1,3]; the corresponding arr subscript represents the row, and the value of arr represents the column

Code implementation :

Note : If a chess piece n has tried all 8 positions and still has no correct solution, go back to the previous chess piece n-1, move it back one place (array[n-1] = i;), and then Traverse to determine n (starting from the first column)

public class Queue8 {
    
    
    //定义皇后的个数
    int max = 8;
    //定义数组array,保存皇后防止位置的结果,比如arr=[0,4,7,5,2,6,1,3];
    int[] array = new int[max];
    static int count = 0;
    public  static void main(String args[]){
    
    
        Queue8 queue8 = new Queue8();
        queue8.check(0);
        System.out.println("共找到多少种解法:"+count);
    }

    /**
     * 放置第n个皇后
     * 递归解决问题的思路:
     *  1. 找到整个递归的终止条件: 当防止第8个皇后结束以后,即n=8时
     *  2. 找到单次递归的任务: 一次递归需要将这个皇后应该放的第n行的 8个列从左到右遍历一遍,如果找到不与前n个皇后冲突的格子,则放入皇后,接下来继续防止n+1个皇后
     *
     *  注意: 如果一个棋子n将8个位置全部尝试后仍然没有正确解,则回回溯到前一个棋子n-1,将其往后移动一位(array[n-1] = i;),再遍历判断n(从第一列开始)
     * @param n
     */
    public void check(int n){
    
    
        if(n == 8){
    
    
            showArray();
            return;
        }

        //依次放入皇后,并判断是否冲突
        for (int i = 0; i <max ; i++) {
    
    
            //先把当前这个皇后放在第n行的第一列
            array[n] = i;
            if(judge(n)){
    
    
                //不冲突,就防止下一个皇后,直到第八个放完
                check(n+1);
            }
            //如果冲突了,继续遍历i++, array[n] = i++;
        }

    }

    /**
     * 需要一个判断棋子是否冲突的方法
     * 判断参数n皇后是否与已经放置的前n-1个皇后冲突
     *     冲突规则:
     *      1.同一列:array[i] == array[n]
     *      2.同一斜线: Math.abs(n-i) == Math.abs(array[n] - array[i])  两个棋子的行距离等于列距离
     * @param n
     * @return
     */
    public boolean judge(int n){
    
    
        for (int i = 0; i <n ; i++) {
    
    
            if(array[i] == array[n] || Math.abs(n-i) == Math.abs(array[n] - array[i])){
    
    
                return false;
            }
        }
        return true;
    }

    //打印一次结果
    public void showArray(){
    
    
        for (int i = 0; i <8 ; i++) {
    
    
            System.out.print(array[i]+" ");
        }
        System.out.println();
        count++;
    }
}

Result :

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

Guess you like

Origin blog.csdn.net/weixin_44634197/article/details/108561844