首页 > 试题广场 >

走迷宫

[编程题]走迷宫
  • 热度指数:3998 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
NowCoder最喜欢游乐场的迷宫游戏,他和小伙伴们比赛谁先走出迷宫。
现在把迷宫的地图给你,你能帮他算出最快走出迷宫需要多少步吗?

输入描述:
输入包含多组数据。

每组数据包含一个10*10,由“#”和“.”组成的迷宫。其中“#”代表墙;“.”代表通路。

入口在第一行第二列;出口在最后一行第九列。

从任意一个“.”点都能一步走到上下左右四个方向的“.”点。


输出描述:
对应每组数据,输出从入口到出口最短需要几步。
示例1

输入

#.########
#........#
#........#
#........#
#........#
#........#
#........#
#........#
#........#
########.#
#.########
#........#
########.#
#........#
#.########
#........#
########.#
#........#
#.######.#
########.#

输出

16
30
1、深度优先遍历




import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        char str[][] = new char[10][10];
        int[][] dp = new int[10][10];//动归数组
        while (scanner.hasNext()) {
            for (int i = 0; i < 10; i++) {
                String ret = scanner.next();
                for (int j = 0; j < 10; j++) {
                    str[i][j] = ret.charAt(j);
                    dp[i][j] = Integer.MAX_VALUE;
                }
            }

            dp[0][1] = 0;
            dfs(str, 0, 1, dp);
            System.out.println(dp[9][8]);
        }
    }

    private static void dfs(char[][] str, int i, int j, int[][] dp) {
        //i j坐标不是终点
        int[][] pos = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};//有四个方向 上下左右
        for (int k = 0; k < 4; k++) {//控制点的四个方向

            // 沿着一个树的分支 走到终点
            int x = i + pos[k][0];
            int y = j + pos[k][1];
            if (x >= 0 && x < 10 && y >= 0 && y < 10 && str[x][y] == '.' && dp[x][y] > dp[i][j] + 1) {
                //不越界 并且是通路 并且没有到达过
                // 如果说已经dp[x][y]已经是从入口到达(x,y)的最短路径了 就不需要从这个点开始找寻最短路径了 因为这个点已经在最短路径之中了
                //如果某一个路径经过这个点的距离更小,这个路径才有可能会是最短路径 

                dp[x][y] = Math.min(dp[i][j] + 1, dp[x][y]);//dp[x][y]保存到达(x,y)下标的最短路径
                if (x == 9 && y == 8) {//找到了其中一个路径 回溯 dp[x][y]保留路径的最终长度 
                    return;
                }
                dfs(str, x, y, dp);//沿着一个树的分支 走到终点
                //递归结束之后 回溯  在for循环的控制下 找到新的路径
            }
        }
    }
}
深度优先遍历,求多个树的路径,后得出最小的,虽然有动归的优化,但是还是会重复许多不必要的结点

2、广度优先遍历

二叉树的层次遍历,从根节点到指定叶子节点 的层数


import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

class Note {
    int x;
    int y;

    public Note(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        char str[][] = new char[10][10];
        while (scanner.hasNext()) {
            for (int i = 0; i < 10; i++) {
                String ret = scanner.next();
                for (int j = 0; j < 10; j++) {
                    str[i][j] = ret.charAt(j);
                }
            }

            System.out.println(bfs(str));
        }
    }


    private static int bfs(char[][] str) {
        Queue<Note> queue = new LinkedList();
        boolean flag[][] = new boolean[10][10];//用于标识元素是否已经被使用
        int max = 0;
        int[][] pos = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};//有四个方向 上下左右
        //第一层 放入根
        Note note = new Note(0, 1);
        queue.add(note);
        flag[0][1] = true;
        while (!queue.isEmpty()) {
            int size = queue.size();
            while (size-- > 0) {
                note = queue.poll();
                //存入这个结点 可以下  右 左 上到的移动的位置
                int x = note.x;
                int y = note.y;
                if (x == 9 && y == 8)///最后从队列取得元素 是出口就结束了
                    return max;
                flag[x][y] = true;//得到 这层元素的下一层元素 这个结点已经被使用
                for (int i = 0; i < 4; ++i) {//控制四个方向
                    int posi = x + pos[i][0];
                    int posj = y + pos[i][1];
                    if (posi >= 0 && posi <= 9 && posj >= 0 && posj <= 9 && !flag[posi][posj] && str[posi][posj] == '.') {
                        Note note1 = new Note(posi, posj);
                        queue.add(note1);
                    }
                }
            }
            //统计完一层结点的下一个位置 也就是获取了一层元素
            max++;
        }
        return max;
    }
}


发表于 2022-09-30 22:49:51 回复(1)
A*算法 通过对比当前路径到达终点所需的最小代价来进行计算
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        char[][] map = new char[10][10];
        while(sc.hasNext()){
            for(int i = 0;i < 10;i++){
                map[i] = sc.next().toCharArray();
            }
            Queue<BetterWay> queue = new PriorityQueue<>();
            queue.add(new BetterWay(0,1,0,0));
            while(!queue.isEmpty()){
                BetterWay bw = queue.poll();
                if(bw.nextCost == 0){
                    System.out.println(bw.size);
                    break;
                }
                int x = bw.x;
                int y = bw.y;
                int nowCost = bw.nowCost;
                int size = bw.size;
                map[x][y] = '#';
                if(checkWay(map,x-1,y)){
                    queue.add(new BetterWay(x-1,y,nowCost,size+1));
                }
                if(checkWay(map,x+1,y)){
                    queue.add(new BetterWay(x+1,y,nowCost,size+1));
                }
                if(checkWay(map,x,y-1)){
                    queue.add(new BetterWay(x,y-1,nowCost,size+1));
                }
                if(checkWay(map,x,y+1)){
                    queue.add(new BetterWay(x,y+1,nowCost,size+1));
                }
            }
        }
    }
    private static boolean checkWay(char[][] map ,int x , int y){
        return x >=0 && x < 10 && y >=0 && y < 10 && map[x][y] == '.';
    }
    private static class BetterWay implements Comparable<BetterWay>{
        int x;
        int y;
        int prevCost;
        int nextCost;
        int nowCost;
        int size;
        public BetterWay(int x, int y,int prevCost,int size){
            this.x = x;
            this.y = y;
            this.prevCost = prevCost;
            this.nextCost = (9 - x) + (8 - y);
            this.nowCost = this.prevCost + this.nextCost;
            this.size = size;
        }
        public int compareTo(BetterWay bw){
            return this.nowCost - bw.nowCost;
        }
    }
}


编辑于 2022-05-22 23:41:21 回复(1)
import java.util.*;
class Position{
    int x;
    int y;
    int level;
    public Position(int x,int y,int level){
        this.x = x;
        this.y = y;
        this.level = level;
    }
}
   

public class Main {
    public static int bfs(char[][] s,int m,int n){
    int[][] direc = {{-1,0},{0,1},{1,0},{0,-1}};
    //迷宫的入口和出口
    Position enter = new Position(0,1,0);
    Position out = new Position(9,8,0);
    
   //标记走过得数组
    boolean[][] flg = new boolean[m][n];
        
    //采用广度优先方式进行遍历
    Queue<Position> queue = new LinkedList<>();
    queue.offer(enter);
    while(!queue.isEmpty()){
        Position cur = queue.poll();
        flg[cur.x][cur.y] = true;
        
        //如果已经到了出口的位置,则直接返回
        if(cur.x == out.x && cur.y == out.y){
            return cur.level;
        }
        for(int i = 0;i < 4;i++){
            Position next = new Position(cur.x + direc[i][0],cur.y + direc[i][1],cur.level + 1);
            //数组下标没有越界,并且该点是合法路径,并且还没有被标记过
            if(next.x >= 0 && next.x < 10 && next.y >= 0 && next.y < 10 && 
               s[next.x][next.y] == '.' && !flg[next.x][next.y]){
                queue.offer(next);
            }
        }
        
    }
     return 0;
}
      public static void main(String[] args){
           Scanner sc = new Scanner(System.in);
          while(sc.hasNext()){
              char[][] map = new char[10][10];
              for(int i = 0;i < 10;i++){
                  String s = sc.next();
                  for(int j = 0;j < 10;j++){
                      map[i][j] = s.charAt(j);
                  }
              }
              System.out.println(bfs(map,10,10));
          }
      }       
}

编辑于 2022-06-06 15:10:35 回复(0)
// dfs深度优先搜索
import java.util.*;
public class Main{
    static int[][] direction = {{0,-1}, {-1,0}, {0,1}, {1,0}};
    public static void dfs(int x, int y, char[][] maze, int[][] map){
        for(int i = 0; i < 4; i++){
            int xx = x + direction[i][0];
            int yy = y + direction[i][1];
            if(xx >= 0 && xx < 10 && yy >= 0 && yy < 10 
              && maze[xx][yy] == '.' && map[xx][yy] > map[x][y]+1){
                map[xx][yy] = map[x][y] + 1;
                dfs(xx, yy, maze, map);
            }
        }
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            char[][] maze = new char[10][10];
            int[][] map = new int[10][10];
            for(int i = 0; i < 10; i++){
                String str = sc.next();
                for(int j = 0; j < 10; j++){
                    maze[i][j] = str.charAt(j);
                    map[i][j] = Integer.MAX_VALUE;
                }
            }
            map[0][1] = 0;
            dfs(0, 1, maze, map);
            System.out.println(map[9][8]);
        }
    }
}
// bfs广度优先搜索
import java.util.*;
public class Main{
    static int[][] direction = {{0,-1}, {-1,0}, {0,1}, {1,0}};
    static class Node{
        int x, y;
        public Node(int x, int y){
            this.x = x;
            this.y = y;
        }
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            char[][] maze = new char[10][10];
            int[][] map = new int[10][10];
            boolean[][] visited = new boolean[10][10];
            for(int i = 0; i < 10; i++){
                String str = sc.next();
                for(int j = 0; j < 10; j++){
                    maze[i][j] = str.charAt(j);
                    if(maze[i][j] == '#'){
                        visited[i][j] = true;
                    }
                }
            }
            Queue<Node> queue = new LinkedList<>();
            queue.offer(new Node(0, 1));
            while(!queue.isEmpty()){
                Node cur = queue.poll();
                for(int i = 0; i < 4; i++){
                    Node next = new Node(cur.x+direction[i][0], cur.y+direction[i][1]);
                    if(next.x >= 0 && next.x < 10 && next.y >= 0 && next.y < 10 
                      && !visited[next.x][next.y]){
                        queue.offer(next);
                        map[next.x][next.y] = map[cur.x][cur.y] + 1;
                        visited[next.x][next.y] = true;
                    }
                }
            }
            System.out.println(map[9][8]);
        }
    }
}


编辑于 2021-07-31 17:48:05 回复(0)
import java.util.*;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while (sc.hasNextLine()) {
			Character[][] map = new Character[10][10];
			for (int i = 0; i < 10; i ++ ) {
				String s = sc.nextLine();
				for (int j = 0; j < 10; j ++ ) {
					map[i][j] = s.charAt(j);
				}
			}
			int[][] direction = {{0, 1}, {0, - 1}, {1, 0}, { - 1, 0}};
			Node start = new Node(0, 1, 0);
			Node end = new Node(9, 8, 0);
			bfs(map, direction, start, end);
		}
	}
	public static void bfs(Character[][] map, int[][] direction, Node start, Node end) {
		boolean[][] visited = new boolean[map.length][map[0].length];
		Queue<Node> queue = new LinkedList<Node>();
		queue.add(start);
		visited[start.x][start.y] = true;
		while ( ! queue.isEmpty()) {
			Node cur = queue.poll();
			if(cur.x == end.x && cur.y == end.y) {
				System.out.println(cur.step);
				break;
			}
			for (int i = 0; i < 4; i ++ ) {
				Node next = new Node(cur.x + direction[i][0], cur.y + direction[i][1], cur.step + 1);
				if(next.x >= 0 && next.x < map.length && next.y >= 0 && next.y < map[0].length && ! visited[next.x][next.y] && map[next.x][next.y] != '#') {
					queue.add(next);
					visited[next.x][next.y] = true;
				}
			}
		}
	}
	static class Node {
		int x;
		int y;
		int step;
		public Node(int x, int y, int step) {
			this.x = x;
			this.y = y;
			this.step = step;
		}
	}
}

发表于 2016-10-08 17:31:06 回复(0)

问题信息

难度:
5条回答 22052浏览

热门推荐

通过挑战的用户

查看代码
走迷宫