数据结构(Java)-迷宫回溯游走问题(递归)

递归的用途

1) 各种数学问题如 :
         八皇后问题 , 汉诺塔 , 阶乘问题 , 迷宫问题 , 球和篮子的问题 (google 编程大赛 )
2) 各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等 .
3) 将用栈解决的问题 -->递 归代码比较简洁

递归需要遵守的重要规则:

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

 

迷宫问题: 

 假设现在有这样的一个迷宫,1为边界,X 为终点。我们从不同的起点出发,采用不同的策略(上下左右)会得到不同的结果。我们希望能够进行随机游走,尽可能地找出最短路径。

111111
11
111
111
1X1
111111

思路:利用随机数使得每次游走的方向都是随机的,每次成功到达终点的路径长度与对应的路径以key-value的形式保存在hashmap中,尝试若干次后输出最短的路径长度以及对应的最短路径。

代码演示:

1.我们首先定义两个全局变量

    public static Integer count=0;//每次成功到达终点所用的步数
    public static Integer successCount=0;//记录成功次数

2.边界初始化函数

 public static String[][] init(){
        //1.初始化一个6x6地图
        String[][] map=new String[6][6];
        for(int row=0;row<6;row++){
            for(int col=0;col<6;col++){
                map[row][col]="0";
            }
        }
        //2.初始化边界
        //第一行和最后一行置1
        for(int col=0;col<6;col++){
            map[0][col]="1";
            map[5][col]="1";
        }
        //第一列和最后一列置1
        for(int row=0;row<6;row++){
            map[row][0]="1";
            map[row][5]="1";
        }
        //设置一些挡板
        for(int col=0;col<2;col++){
            map[2][col]="1";
            map[3][5-col]="1";
        }
        //3.看一下初始边界
        /*for(int row=0;row<6;row++){
            for(int col=0;col<6;col++){
                System.out.print(map[row][col]+"  ");
            }
            System.out.println();
        }*/
        return map;
    }
   

3.模式选择函数,选择向上还是左、右、下? 

 public static boolean mode(int index,String[][] map,int i,int j){
        switch (index){
            case 1:return go(map,i,j+1);
            case 2:return go(map,i,j-1);
            case 3:return go(map,i+1,j);
            case 4:return go(map,i-1,j);
            default:throw new RuntimeException("模式选择有误!");
        }
    }

 4.取map中最小的key

 //取出map中最小的key
    public static Integer getMinKey(Map<Integer,String[][]> map){
        if(map==null){
            return null;
        }else{
            Set<Integer> set=map.keySet();
            Object[] array = set.toArray();
            Arrays.sort(array);
            return (Integer)array[0];
        }
    }

5.游走函数(利用递归)

//对单个点的定义如下:
    // 0:未走过
    // 1:障碍物
    // ^:已走
    // x: 已走,但是死路
    // 假设目标是右下角,即 map[4][4],起始坐标(i,j),遵循上、右、下、左的寻路原则
    public static boolean go(String[][] map,int i,int j){
        //随机生成1-4四个数字,选择不同的前进方向
        Random random=new Random();
        int[] mode=new int[4];
        for(int num=0;num<4;num++){
            mode[num] = random.nextInt(4)+1;
        }
        //如果地图右下角的点已经置“ ^ ”,就表明已经走通了,成功了耶!
        if(map[4][4].equals("^")){
            System.out.print("成功计数:"+(++successCount)+",");
            if(count!=0) System.out.println("本次游走距离为"+count);
            return true;
            //这个点没走过的话就标记走过,然后继续寻路
        }else {
            if(map[i][j].equals("0")){
                map[i][j]="^";
                count+=1;
                if(mode(mode[0],map,i,j)){
                    return true;
                }else if(mode(mode[1],map,i,j)){
                    return true;
                }else if(mode(mode[2],map,i,j)){
                    return true;
                }else if(mode(mode[3],map,i,j)){
                    return true;
                    //如果上下左右都走不通,那就标记为“ X ” ,此路不通请绕路!
                }else {
                    map[i][j]="x";
                       //有时走到死路的话需要返回重走,但走死路的这几步我不能算上去吧
                    count-=1;
                    return false;
                }
                //反正走不下去了,失败!
            }else {
                return false;
            }
        }
    }

6.主函数

public static void main(String[] args) {
        int tryTime=100;//总尝试次数
        System.out.println("总尝试次数:"+tryTime);
        //保存每次成功游走的结果
        Map<Integer,String[][]> result=new HashMap<>();
        while(tryTime>0){
            String[][] map=init();
            //如果成功走到终点了就记录下这次的结果
            if(go(map, 1, 1)){
                result.put(count,map);
                count=0;
            }
            tryTime--;
        }
        System.out.println();
        //取出最短路径长度及最短路径
        System.out.print("最短路径为,"+getMinKey(result));
        System.out.println("对应的路径如下:");
        for(int row=0;row<6;row++){
            for(int col=0;col<6;col++){
                System.out.print(result.get(getMinKey(result))[row][col]+"  ");
            }
            System.out.println();
        }
    }

7.测试:

总尝试次数:100
成功计数:1,本次游走距离为11
成功计数:2,本次游走距离为7
成功计数:3,本次游走距离为7
成功计数:4,本次游走距离为9
成功计数:5,本次游走距离为11
成功计数:6,本次游走距离为7
成功计数:7,本次游走距离为11
成功计数:8,本次游走距离为7
成功计数:9,本次游走距离为7
成功计数:10,本次游走距离为7
成功计数:11,本次游走距离为7
成功计数:12,本次游走距离为7
成功计数:13,本次游走距离为7
成功计数:14,本次游走距离为7
成功计数:15,本次游走距离为7
成功计数:16,本次游走距离为9
成功计数:17,本次游走距离为7
成功计数:18,本次游走距离为9
成功计数:19,本次游走距离为7
成功计数:20,本次游走距离为7
成功计数:21,本次游走距离为11
成功计数:22,本次游走距离为7
成功计数:23,本次游走距离为9
成功计数:24,本次游走距离为11
成功计数:25,本次游走距离为11
成功计数:26,本次游走距离为7
成功计数:27,本次游走距离为11
成功计数:28,本次游走距离为9
成功计数:29,本次游走距离为9
成功计数:30,本次游走距离为7
成功计数:31,本次游走距离为9

最短路径为,7对应的路径如下:
1  1  1  1  1  1  
1  ^  ^  x  x  1  
1  1  ^  x  x  1  
1  x  ^  ^  1  1  
1  x  x  ^  ^  1  
1  1  1  1  1  1  

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值