2018校招真题在线编程-牛客网

题目描述
    假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙。


输入描述
    迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N,后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
输出描述
    路径的长度,是一个整数

示例1
    输入
        5 5
        02111
        01a0A
        01003
        01001
        01111
    输出
        7


分析:普通的深度遍历BFS添加了钥匙这个状态,钥匙的状态用二进制数表示,最多10 把钥匙,那就是1024。isVisted[x][y][key]的意义就是:横坐标为x,纵坐标为y,钥匙状态为key的点是否访问过,0未访问,1访问过。int[][] next = {{-1,0},{0,1},{1,0},{0,-1}};分别表示一个点往左上右下走。java.util.Queue.poll()删除队列头节点,若队列为空,则返回null。key = key | (1 << (G[x][y] - 'a'));若遇到a-z,则拾起钥匙。key & (1 << (G[x][y] - 'A'));判断已拾起的钥匙是否与门匹配。


package com.nowcoder.schoolEnrollment2018;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/**
 * 迷宫寻路
 * @ClassName: PinDuoDuo4.java
 * @Description:
 * @author: Henray
 * @version: 1.0
 * @Date: 2019年3月7日
 */
public class PinDuoDuo4 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 矩阵的行数M和列数N
        int M = sc.nextInt();
        int N = sc.nextInt();
        char[][] G = new char[M][N];
        sc.nextLine();
        for (int i = 0; i < M; i++)
            G[i] = sc.nextLine().toCharArray();
        for (int i = 0; i < M; i++) {
            for (int j = 0; i < N; j++) {
                if (G[i][j] == '2') {
                    System.out.println(BFS(i, j, M, N, G));
                    return;
                }
            }
        }
    }

    private static int BFS(int si, int sj, int M, int N, char[][] G) {
        Queue<Node> queue = new LinkedList<>();
        int[][][] isVisted  = new int[M][N][1025];
        int[][] next = {{-1,0},{0,1},{1,0},{0,-1}};// 左上右下
        queue.offer(new Node(si, sj, 0, 0));
        while (!queue.isEmpty()) {
            Node node = queue.poll();
            for (int i = 0; i < 4; i++) {
                int x = node.x + next[i][0];
                int y = node.y + next[i][1];
                int key = node.key;
                if (x < 0 || x >= M || y < 0 || y >= N || G[x][y] == '0')
                    continue;
                else if (G[x][y] == '3')
                    return node.step + 1;
                else if (G[x][y] <= 'z' && G[x][y] >= 'a')
                    key = key | (1 << (G[x][y] - 'a'));
                else if (G[x][y] <= 'Z' && G[x][y] >= 'A' && (key & (1 << (G[x][y] - 'A'))) == 0)
                    continue;
                if (isVisted [x][y][key] == 0) {
                    isVisted [x][y][key] = 1;
                    queue.offer(new Node(x, y, key, node.step + 1));
                }
            }
        }
        return -1;
    }

    private static class Node {
        int x;
        int y;
        int key;
        int step;
        public Node(int x, int y, int key, int step) {
            super();
            this.x = x;
            this.y = y;
            this.key = key;
            this.step = step;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值