Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5e554ce

Browse files
authored
Improved task 864.
1 parent 897885b commit 5e554ce

File tree

1 file changed

+78
-69
lines changed
  • src/main/java/g0801_0900/s0864_shortest_path_to_get_all_keys

1 file changed

+78
-69
lines changed

‎src/main/java/g0801_0900/s0864_shortest_path_to_get_all_keys/Solution.java‎

Lines changed: 78 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3,88 +3,97 @@
33
// #Hard #Breadth_First_Search #Bit_Manipulation
44

55
import java.util.LinkedList;
6+
import java.util.Queue;
67

8+
@SuppressWarnings("java:S135")
79
public class Solution {
8-
class Status {
9-
int key;
10-
int i;
11-
int j;
10+
private int m;
11+
private int n;
1212

13-
public Status(int key, int i, int j) {
14-
this.key = key;
15-
this.i = i;
16-
this.j = j;
13+
public int shortestPathAllKeys(String[] stringGrid) {
14+
// strategy: BFS + masking
15+
m = stringGrid.length;
16+
n = stringGrid[0].length();
17+
char[][] grid = new char[m][n];
18+
int index = 0;
19+
// convert to char Array
20+
for (String s : stringGrid) {
21+
grid[index++] = s.toCharArray();
1722
}
18-
}
19-
20-
public int shortestPathAllKeys(String[] grid) {
21-
int success = 0;
22-
int startI = 0;
23-
int startJ = 0;
24-
int rows = grid.length;
25-
int cols = grid[0].length();
26-
for (int i = 0; i < rows; i++) {
27-
for (int j = 0; j < cols; j++) {
28-
char c = grid[i].charAt(j);
29-
if (c >= 'A' && c <= 'F') {
30-
success |= 1 << (c - 'A');
31-
}
32-
33-
if (c == '@') {
34-
startI = i;
35-
startJ = j;
23+
// number of keys
24+
int count = 0;
25+
Queue<int[]> q = new LinkedList<>();
26+
for (int i = 0; i < m; i++) {
27+
for (int j = 0; j < n; j++) {
28+
// find starting position
29+
if (grid[i][j] == '@') {
30+
q.add(new int[] {i, j, 0});
3631
}
37-
}
38-
}
39-
int[][][] dist = new int[1 << 6][rows][cols];
40-
for (int i = 0; i < dist.length; i++) {
41-
for (int j = 0; j < dist[0].length; j++) {
42-
for (int k = 0; k < dist[0][0].length; k++) {
43-
dist[i][j][k] = Integer.MAX_VALUE;
32+
// count number of keys
33+
if ('a' <= grid[i][j] && grid[i][j] <= 'f') {
34+
count++;
4435
}
4536
}
4637
}
47-
LinkedList<Status> queue = new LinkedList<>();
48-
queue.offer(new Status(0, startI, startJ));
49-
dist[0][startI][startJ] = 0;
50-
int path = 0;
51-
int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
52-
while (!queue.isEmpty()) {
53-
int size = queue.size();
54-
while (size-- > 0) {
55-
Status status = queue.poll();
56-
int key = status.key;
57-
int x = status.i;
58-
int y = status.j;
59-
if (key == success) {
60-
return path;
38+
int[] dx = {-1, 0, 1, 0};
39+
int[] dy = {0, -1, 0, 1};
40+
// this is the amt of keys we need
41+
int target = (1 << count) - 1;
42+
// keep track of position and current state
43+
boolean[][][] visited = new boolean[m][n][target + 1];
44+
// set initial position and state to true
45+
visited[q.peek()[0]][q.peek()[1]][0] = true;
46+
int steps = 0;
47+
while (!q.isEmpty()) {
48+
// use size to make sure everything is on one level
49+
int size = q.size();
50+
while (--size >= 0) {
51+
int[] curr = q.poll();
52+
int x = curr[0];
53+
int y = curr[1];
54+
int state = curr[2];
55+
// found all keys
56+
if (state == target) {
57+
return steps;
6158
}
62-
for (int[] dir : dirs) {
63-
int xx = x + dir[0];
64-
int yy = y + dir[1];
65-
if (xx >= 0
66-
&& xx < rows
67-
&& yy >= 0
68-
&& yy < cols
69-
&& grid[xx].charAt(yy) != '#') {
70-
int nextKey = key;
71-
char c = grid[xx].charAt(yy);
72-
if (c >= 'a' && c <= 'f') {
73-
nextKey = key | (1 << (c - 'a'));
74-
}
75-
76-
if (c >= 'A' && c <= 'F' && (nextKey & (1 << (c - 'A'))) == 0) {
77-
continue;
78-
}
79-
if (path + 1 < dist[nextKey][xx][yy]) {
80-
dist[nextKey][xx][yy] = path + 1;
81-
queue.offer(new Status(nextKey, xx, yy));
82-
}
59+
for (int i = 0; i < 4; i++) {
60+
int nx = x + dx[i];
61+
int ny = y + dy[i];
62+
// use new state so we don't mess up current state
63+
int nState = state;
64+
// out of bounds or reached wall
65+
if (!inBounds(nx, ny) || grid[nx][ny] == '#') {
66+
continue;
67+
}
68+
// found key
69+
// use OR to add key to our current state because if we already had the key the
70+
// digit would still be 1/true
71+
if ('a' <= grid[nx][ny] && grid[nx][ny] <= 'f') {
72+
// bit mask our found key
73+
nState = state | (1 << (grid[nx][ny] - 'a'));
74+
}
75+
// found lock
76+
// use & to see if we have the key
77+
// 0 means that the digit we are looking at is 0
78+
// need a 1 at the digit spot which means there is a key there
79+
if ('A' <= grid[nx][ny]
80+
&& grid[nx][ny] <= 'F'
81+
&& ((nState & (1 << (grid[nx][ny] - 'A'))) == 0)) {
82+
continue;
83+
}
84+
// not seen before
85+
if (!visited[nx][ny][nState]) {
86+
q.add(new int[] {nx, ny, nState});
87+
visited[nx][ny][nState] = true;
8388
}
8489
}
8590
}
86-
path++;
91+
steps++;
8792
}
8893
return -1;
8994
}
95+
96+
private boolean inBounds(int x, int y) {
97+
return x >= 0 && x < m && y >= 0 && y < n;
98+
}
9099
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /