3
private static final int[][] DIRS = new int[][] {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};5
public int shortestPathAllKeys(String[] grid) {6
int m = grid.length, n = grid[0].length();7
int numKeys = 0, startRow = -1, startCol = -1;9
for (int i = 0; i < m; i++) {10
for (int j = 0; j < n; j++) {11
char c = grid[i].charAt(j);16
} else if (isKey(c)) numKeys++;19
if (startRow == -1) return -1;21
int keyMask = (1 << numKeys) - 1;22
State start = new State(startRow, startCol, 0);23
Queue<State> queue = new LinkedList();24
Set<State> visited = new HashSet();30
while (!queue.isEmpty()) {31
int size = queue.size();34
int i = queue.peek().i;35
int j = queue.peek().j;36
int keys = queue.peek().keys;39
if (keys == keyMask) return steps;41
for (int[] dir : DIRS) {46
if (di < 0 || dj < 0 || di == m || dj == n) continue;48
char c = grid[di].charAt(dj);50
if (isWall(c)) continue;52
if (isLock(c) && !isKeyPresent(keys, c)) continue;54
if (isKey(c)) newKeys |= (1 << (c - 'a'));56
State newState = new State(di, dj, newKeys);58
if (visited.add(newState)) queue.offer(newState);66
private boolean isLock(char c) {67
return c >= 'A' && c <= 'Z';70
private boolean isKey(char c) {71
return c >= 'a' && c <= 'z';74
private boolean isWall(char c) {78
private boolean isStart(char c) {82
private boolean isKeyPresent(int keys, char lock) {83
return (keys & (1 << (lock - 'A'))) != 0;88
public int i, j, keys;90
public State(int i, int j, int keys) {97
public boolean equals(Object obj) {98
if (!(obj instanceof State)) return false;99
State that = (State) obj;100
return i == that.i && j == that.j && keys == that.keys;104
public int hashCode() {107
hash = hash * prime + i;108
hash = hash * prime + j;109
hash = hash * prime + keys;