864. Shortest Path to Get All Keys

这题和847 差不多,都是要用位置加状态表示一个node
其实相当于对一个暴力解的优化。
graph里的node定下来之后,就是常规的BFS思路了 。

class Solution {
    int[][] OFFSETS;
    public int shortestPathAllKeys(String[] grid) {
        int keyCnt = getKeyCnt(grid);
        int initalState = 0;
        int targetState = (1 << keyCnt) - 1;
        int N = grid.length;
        int M = grid[0].length();
        OFFSETS = new int[][]{{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
        int[][][] visitedBest = new int[targetState + 1][N][M];
        for (int i = 0; i <= targetState; i++) {
            for (int j = 0; j < N; j++) {
                for (int k = 0; k < M; k++) {
                    visitedBest[i][j][k] = Integer.MAX_VALUE; }}}
                
        int[] startPoint = getStartPoint(grid);
        Queue queue = new LinkedList<>();
        queue.offer(new int[] {0, startPoint[0], startPoint[1]});
        visitedBest[0][startPoint[0]][startPoint[1]] = 0;
        int level = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int[] node = queue.poll();
                for (int[] next : getNext(node, grid)) {
                    
                    char ch = grid[next[0]].charAt(next[1]);
                    int nextState = node[0];
                    if (isKey(ch)) nextState |= (1 << (ch - 'a'));
                    if (visitedBest[nextState][next[0]][next[1]] != Integer.MAX_VALUE) continue;
                    visitedBest[nextState][next[0]][next[1]] = level + 1;
                    if (nextState == targetState) return level + 1;
                    queue.offer(new int[]{nextState, next[0], next[1]});
                } 
            }
            level++;
        }
        return -1;
    }
    //@ToDo getKeyCnt(grid);
    private int getKeyCnt(String[] grid) {
        int cnt = 0;
        for (String line : grid) {
            for (char ch : line.toCharArray()) {
                if (isKey(ch)) cnt++;
            }
        }
        return cnt;
    }
    //@ToDo if (isKey(ch));
    private boolean isKey(char ch) {
        return (ch >= 'a' && ch <= 'f');
    }
    private boolean isLock(char ch) {
        return (ch >= 'A' && ch <= 'F');
    }
        
    //@ToDo getStartPoint(grid);
    private int[] getStartPoint(String[] grid) {
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length(); j++) {
                if (grid[i].charAt(j) == '@') return new int[]{i, j};
            }
        }
        return null;
    }
    //@ToDo int[] next : getNext(node, grid);
    private List getNext(int[] node, String[] grid) {
        int r = node[1], c = node[2];
        List ans = new ArrayList<>();
        for (int[] os : OFFSETS) {
            int nr = r + os[0], nc = c + os[1];
            
            if (nr < 0 || nc < 0 || nr >= grid.length || nc >= grid[0].length()) continue;
            if (grid[nr].charAt(nc) == '#') continue;
            if (isLock(grid[nr].charAt(nc))) {
                char lock = grid[nr].charAt(nc);
                if((node[0] & (1 << (lock - 'A'))) == 0) continue;
            }
            ans.add(new int[]{nr, nc});
        }
        
        return ans;
    }
}

你可能感兴趣的:(864. Shortest Path to Get All Keys)