图论17(Leetcode864.获取所有钥匙的最短路径)

用二进制表示获得的钥匙,假设n=钥匙个数

000000000代表没有钥匙,0000000001代表有idx为1的钥匙,0000000011代表有idx=1,2的钥匙

(这方法巧妙又复杂..

代码:

java 复制代码
class Solution {
    static int[][] dirs = {{-1,0},{1,0},{0,-1},{0,1}};
    public int shortestPathAllKeys(String[] grid) {
        int m = grid.length, n = grid[0].length();
        int startx = 0,starty = 0;
        Map<Character, Integer> keyToIndex = new HashMap<>();
        //存钥匙的字母和对应的idx序号
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[i].length();j++){
                if(grid[i].charAt(j)=='@'){
                    startx = i;
                    starty = j;
                }else if(Character.isLowerCase(grid[i].charAt(j))){
                    if(!keyToIndex.containsKey(grid[i].charAt(j))){
                        int idx = keyToIndex.size();
                        keyToIndex.put(grid[i].charAt(j), idx);
                    }                    
                }
            }
        }
        Queue<int[]> queue = new ArrayDeque<int[]>();
        int[][][] dist = new int[m][n][1<<keyToIndex.size()];
        //第三维是2的size次方 列举钥匙的所有可能
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                Arrays.fill(dist[i][j],-1);
            }
        } 
        queue.offer(new int[]{startx,starty,0});
        dist[startx][starty][0] = 0;
        while(!queue.isEmpty()){
            int[] arr = queue.poll();
            int x = arr[0],y = arr[1],mask = arr[2];//mask是钥匙的排列
            for(int i=0;i<4;i++){
                int nx = x + dirs[i][0];
                int ny = y + dirs[i][1];
                if(nx>=0 && nx<m && ny>=0 && ny<n &&grid[nx].charAt(ny)!='#'){
                    if(grid[nx].charAt(ny)=='.'||grid[nx].charAt(ny)=='@'){
                        if(dist[nx][ny][mask] == -1){
                            dist[nx][ny][mask] = dist[x][y][mask]+1;
                            queue.offer(new int[]{nx,ny,mask});
                        }
                    }else if(Character.isLowerCase(grid[nx].charAt(ny))){
                        int idx = keyToIndex.get(grid[nx].charAt(ny));
                        if(dist[nx][ny][mask|(1<<idx)] == -1){
                            dist[nx][ny][mask|(1<<idx)] = dist[x][y][mask]+1;
                            if((mask|(1<<idx))==(1<<keyToIndex.size())-1){
                                return dist[nx][ny][mask|(1<<idx)];
                            }
                            queue.offer(new int[]{nx,ny,mask|(1<<idx)});
                        }
                    }else{
                        int idx = keyToIndex.get(Character.toLowerCase(grid[nx].charAt(ny)));
                        if((mask&(1<<idx))!=0&&dist[nx][ny][mask]==-1){
                            dist[nx][ny][mask] = dist[x][y][mask]+1;
                            queue.offer(new int[]{nx,ny,mask});
                        }
                    }
                }
            }

        }  
        return -1;     
    }
}
相关推荐
JieE2121 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
JieE2122 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack203 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树3 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2123 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2123 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术4 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦4 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
用户497863050734 天前
(一)小红的数组操作
算法·编程语言