题解 | #迷宫问题#

迷宫问题

https://www.nowcoder.com/practice/cf24906056f4488c9ddb132f317e03bc

调了好长时间,不知道为何定义成中等的,这玩意儿要是能一两个小时之内调通的,都是高手啊。

import java.util.*;
import java.lang.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            int n = in.nextInt();
            int m = in.nextInt();
            int[][] t = new int[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    t[i][j] = in.nextInt();
                }
            }
            Stack<String> out = new Stack<>();//存放走过的正确路径,用来最后输出
            Linju first = new Linju(0, 0, n - 1, m - 1);//定义第一个点对象,设置点坐标边界
            LinkedList<String> pres = new LinkedList<>();//记忆已经走过的路径,包含走错的
            LinkedList<Linju> lll = new LinkedList<>();//存放每个点的邻居,每前进一步清空给下个点用
            Stack<Linju> jiedian = new Stack<>();//遇到一个分叉路口,纪录当前路口的点为节点,方便走错时返回来
            out.add(first.zuobiao());
            Linju now = first;
            //若未到最后一个点,就一直走
            while (!(now.x == n - 1 && now.y == m - 1) && t[now.x][now.y] == 0) {
                pres.add(now.zuobiao());//把当前点加入记忆
                //取当前点的上下左右邻居,若没有返回null
                Linju r = now.right();
                Linju l = now.left();
                Linju d = now.down();
                Linju u = now.up();
                //判断这些邻居中哪些是下一步可以走的,存入邻居组                
                for (Linju i : new Linju[] {r, l, d, u}) {
                    if (i != null && t[i.x][i.y] == 0 && !pres.contains(i.zuobiao())) {
                        lll.add(i);
                        continue;
                    }

                }

                if(lll.size()>1){
                    jiedian.add(now);//标记分叉口的节点
                }

                if (lll.size() > 0) {//若存在可走的点,则选择一个去走
                    now = lll.get(0);
                    lll.clear();
                    out.add(now.zuobiao());

                } else if (lll.size() == 0) {//若已无路可走,返回到最近的一个分叉口重新走
                    Linju prejie = jiedian.pop();
                    int jieind = out.indexOf(prejie.zuobiao());
                    for(int i=out.size()-1;i>jieind;i--){
                        out.pop();//处理掉走错的点
                    }
                    now = prejie;
                }
            }
            //输出正确的路径
            for (String s : out) {
                System.out.println(s);
            }
        }
    }
    //将点封装成对象,用于取坐标及上下左右的邻居
    public static class Linju {
        int x = 0;
        int y = 0;
        int rb = 0;
        int cb = 0;
        Linju(int x, int y, int ri, int ci) {
            this.x = x;
            this.y = y;
            this.rb = ri;
            this.cb = ci;
        }
        String zuobiao() {
            return String.format("(%d,%d)", this.x, this.y);
        }
        Linju right() {
            if (this.y < this.cb) {
                return new Linju(this.x, this.y + 1, this.rb, this.cb);
            } else {
                return null;
            }
        }
        Linju left() {
            if (this.y > 0) {
                return new Linju(this.x, this.y - 1, this.rb, this.cb);
            } else {
                return null;
            }
        }
        Linju down() {
            if (this.x < this.rb) {
                return new Linju(this.x + 1, this.y, this.rb, this.cb);
            } else {
                return null;
            }
        }
        Linju up() {
            if (this.x > 0) {
                return new Linju(this.x - 1, this.y, this.rb, this.cb);
            } else {
                return null;
            }
        }
    }
}

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务