그리드가 있다고 가정합니다. 기호가 거의 없습니다. "." 는 빈 셀, "#"은 벽, "@"는 시작점, ("a", "b", ...) 모두 키, ("A", "B", ...) ) 모두 자물쇠입니다. 출발점에서 출발하여 4방향(좌,우,상,하) 중 하나로 한 칸씩 걷는 것이 1동작이다. 우리는 그리드 밖으로 나가지 않을 것이며 우리의 길을 막는 벽이 있습니다. 열쇠 위를 걸어가면 열쇠를 줍습니다. 해당 열쇠가 없으면 자물쇠를 넘을 수 없습니다.
A, B 등의 각 자물쇠에 대해, b 등의 키가 있으므로 자물쇠는 대문자와 동일하고 키는 소문자와 동일합니다.
모든 키를 얻으려면 가장 적은 수의 이동을 찾아야 합니다. 불가능한 경우 -1을 반환합니다.
따라서 입력이 ["@.a.#",###.#","b.A.B"]와 같으면 출력은 8
이 됩니다.이 문제를 해결하기 위해 다음 단계를 따릅니다. −
-
n :=행 수, m :=열 수
-
크기가 3인 배열 시작을 정의합니다.
-
cnt :=0
-
initialize i :=0의 경우, i
-
j 초기화의 경우:=0, j
-
grid[i, j]가 '@'와 같으면 -
-
시작[1] :=나, 시작[2] :=j
-
-
grid[i, j]>='a'이고 grid[i, j] <='f'이면 -
-
cnt :=cnt 및 grid[i, j]의 최대값 - 'a' + 1
-
-
-
-
방문한 한 세트 정의
-
요구사항 :=2^(cnt - 1)
-
배열의 하나의 대기열 q 정의
-
q에 시작 삽입
-
방문에 시작 삽입
-
레벨 :=0
-
동안(q가 비어 있지 않음) -
를 수행합니다.-
sz :=q의 크기
-
sz가 0이 아닌 동안 각 반복 후에 sz를 감소시키고 -
-
배열 정의 curr :=q의 앞 요소
-
q에서 요소 삭제
-
키 :=curr[0]
-
키가 req와 같으면 -
-
반환 수준
-
-
x :=curr[1], y :=curr[2]
-
prevKey :=키
-
initialize i :=0의 경우, i <4일 때 업데이트(i를 1만큼 증가), 수행 -
-
nx :=x + dir[i, 0], ny :=y + dir[i, 1]
-
키 :=이전 키
-
nx>=0이고 ny>=0이고 nx
-
grid[nx, ny]가 '#'과 같으면 -
-
다음 부분은 무시하고 다음 반복으로 건너뜁니다.
-
-
grid[nx, ny]>='a'이고 grid[nx, ny] <='f'이면 -
-
key :=key OR (2^(grid[nx, ny] - 'a'의 ASCII))
-
-
grid[nx, ny]>='A'이고 grid[nx, ny] <='F'이면 -
-
(오른쪽으로 이동 키(grid[nx, ny] - ASCII of 'A') timesAND 1)가 0과 같으면 -
-
다음 부분은 무시하고 다음 반복으로 건너뜁니다.
-
-
-
배열 상태 정의({ key, nx, ny })
-
상태가 방문 중인 경우 -
-
다음 부분은 무시하고 다음 반복으로 건너뜁니다.
-
-
상태를 q
에 삽입 -
방문 상태 삽입
-
-
-
-
(레벨 1 증가)
-
-
반환 -1
이해를 돕기 위해 다음 구현을 살펴보겠습니다. −
예
#include <bits/stdc++.h>
using namespace std;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
class Solution {
public:
int shortestPathAllKeys(vector<string>& grid) {
int n = grid.size();
int m = grid[0].size();
vector<int> start(3);
int cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == '@') {
start[1] = i;
start[2] = j;
}
if (grid[i][j] >= 'a' && grid[i][j] <= 'f') {
cnt = max(cnt, grid[i][j] - 'a' + 1);
}
}
}
set<vector<int> > visited;
int req = (1 << cnt) - 1;
queue<vector<int> > q;
q.push(start);
visited.insert(start);
int level = 0;
while (!q.empty()) {
int sz = q.size();
while (sz--) {
vector<int> curr = q.front();
q.pop();
int key = curr[0];
if (key == req)
return level;
int x = curr[1];
int y = curr[2];
int nx, ny;
int prevKey = key;
for (int i = 0; i < 4; i++) {
nx = x + dir[i][0];
ny = y + dir[i][1];
key = prevKey;
if (nx >= 0 && ny >= 0 && nx < n && ny < m) {
if (grid[nx][ny] == '#')
continue;
if (grid[nx][ny] >= 'a' && grid[nx][ny] <=
'f') {
key |= (1 << (grid[nx][ny] - 'a'));
}
if (grid[nx][ny] >= 'A' && grid[nx][ny] <=
'F') {
if (((key >> (grid[nx][ny] - 'A')) & 1)
== 0)
continue;
}
vector<int> state({ key, nx, ny });
if (visited.count(state))
continue;
q.push(state);
visited.insert(state);
}
}
}
level++;
}
return -1;
}
};
main(){
Solution ob;
vector<string> v = {"@.a.#","###.#","b.A.B"};
cout << (ob.shortestPathAllKeys(v));
} 입력
{"@.a.#","###.#","b.A.B"} 출력
8