『牛客网||每日一练』---->米兔走迷宫

目录

每日一句

 作者简介

『牛客网||每日一题』米兔走迷宫

1.每日一题

2.解题思路

        2.1 思路分析 

        2.1 核心代码(回溯)

        2.3 完整代码 

        2.4 运行结果 

        2.5 官方答案


每日一句

生活是一只你看不见的储蓄罐,你投入的每一份努力都不会白费

 作者简介

🏡个人主页:XiaoChen_Android

📚学习专栏:牛客网

🕒发布日期:2022/8/24

在这里插入图片描述

『牛客网||每日一题』米兔走迷宫

1.每日一题

原题链接--->点我

2.解题思路

        2.1 思路分析 

对于类似于走迷宫找东西的题目,首先就会想到用回溯法,此题只是经典回溯问题的小进化

        S1:首先先找到回溯函数需要的几个参数,第一个是方向的参数i和j,第二个就需要一个数组来判断是否访问,第三个就是迷宫的图,最后一个参数就是距离;

        S2:接下来要找到不能继续回溯的条件,首先不能越界即,即不能超出迷宫,第二个就是该点没有被访问,第三个就是该点一定要是可走的,即不能为墙;

        S3:由于迷宫是有多条路径的,每次找到传送门需要选择最短的路径,所以新增一个变量step来记录每次最短的路径;

        S4:四个方向遍历,在遍历完之后要撤销该点已经访问,即改变used数组的值;

        S5:在开始走迷宫时,需要先找到迷宫的起点,用两个变量记录该点的坐标,从该点进行回溯;

         2.1 核心代码(回溯)

    public static void backTrace(char[][] map , int i , int j , boolean[][] used , int ans){
        int length = map.length;
        int width = map[0].length;
        //越界检查  不能是墙#  不能已经走过
        if((i < 0 || i >= length || j < 0 || j >= width || map[i][j] == '#' || used[i][j]) == true){
            return ;
        }
        //如果是路,步数++,并记录为已走过
        if(map[i][j] == '.' || map[i][j] == '@'){
            ans++;
            used[i][j] = true;
        }
        //如果是传送门说明找到一条路径,此时要选择路径短的那条
        if(map[i][j] == '$'){
            if(ans < step)
                step = ans;
            return ;
        }
        backTrace(map,i - 1,j,used,ans);
        backTrace(map,i + 1,j,used,ans);
        backTrace(map,i,j - 1,used,ans);
        backTrace(map,i,j + 1,used,ans);
        used[i][j] = false;
    }

        2.3 完整代码 

import java.util.Scanner;

public class Main5 {
    static int step = 99999;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int width = sc.nextInt();
        int length = sc.nextInt();
        char[][] map = new char[length][width];
        boolean[][] used = new boolean[length][width];
        String[] str = new String[length];
        for(int i = 0 ; i < length ; i++){
            str[i] = sc.next();
        }
        int idx = 0,idy = 0;
        for(int i = 0 ; i < length ; i++){
            for(int j = 0 ; j < width ; j++){
                used[i][j] = false;
                map[i][j] = str[i].charAt(j);
                if(map[i][j] == '@'){
                    idx = i;
                    idy = j;
                }
            }
        }
        //记录每次路径的长度
        int ans = 1;
        backTrace(map,idx,idy,used,ans);
        System.out.println(step);
    }
    public static void backTrace(char[][] map , int i , int j , boolean[][] used , int ans){
        int length = map.length;
        int width = map[0].length;
        //越界检查  不能是墙#  不能已经走过
        if((i < 0 || i >= length || j < 0 || j >= width || map[i][j] == '#' || used[i][j]) == true){
            return ;
        }
        //如果是路,步数++,并记录为已走过
        if(map[i][j] == '.' || map[i][j] == '@'){
            ans++;
            used[i][j] = true;
        }
        //如果是传送门说明找到一条路径,此时要选择路径短的那条
        if(map[i][j] == '$'){
            if(ans < step)
                step = ans;
            return ;
        }
        backTrace(map,i - 1,j,used,ans);
        backTrace(map,i + 1,j,used,ans);
        backTrace(map,i,j - 1,used,ans);
        backTrace(map,i,j + 1,used,ans);
        used[i][j] = false;
    }
}

        2.4 运行结果 

        2.5 官方答案

import java.util.Scanner;
public class Main {
static int h, w;
static int startX, startY;
static int count;
static int[][] map;
static int[][] visit;
static int min;
static final int move[][] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
public static void dfs(int x, int y) {
count++;
visit[x][y] = 1;
if (map[x][y] == 3) {
if (count < min) {
min = count;
}
return;
}
if (count >= min) {
return;
}
for (int i = 0; i < 4; i++) {
int newX = x + move[i][0];
int newY = y + move[i][1];
if (check(newX, newY)) {
dfs(newX, newY);
count--;
visit[newX][newY] = 0;
}
}
}
public static boolean check(int x, int y) {
return x >= 0 && x < h && y >= 0 && y < w && map[x][y] != 0 && visit[x][y] == 0;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
w = sc.nextInt();
h = sc.nextInt();
map = new int[h][w];
visit = new int[h][w];
min = h*w;
count = 0;
for (int i = 0; i < h; i++) {
String temp = sc.next();
for (int j = 0; j < w; j++) {
char a = temp.charAt(j);
switch (a) {
case '#':
map[i][j] = 0;
break;
case '.':
map[i][j] = 1;
break;
case '@':
map[i][j] = 2;
startX = i;
startY = j;
break;
case '$':
map[i][j] = 3;
break;
}
}
}
dfs(startX, startY);
System.out.println(min);
sc.close();
}
}

我的答案仅供参考,各位大佬有更好的方法可以分享出来


🍁 类似题目推荐:

牛客网刷题,让你的代码能力更上一层

 如果文章对各位大佬有帮助就支持一下噢,新手尝试,不好的地方请各位大佬多多指教! 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值