1298 - Maximum Candies You Can Get from Boxes
info
- 문제 보기: 1298 - Maximum Candies You Can Get from Boxes
- 소요 시간: 35분 6초
- 풀이 언어:
java
- 체감 난이도: 3️⃣
- 리뷰 횟수: ✅
풀이 키워드
스포주의
bfs
구현
풀이 코드
info
- 메모리: 57020 KB
- 시간: 3 ms
class Solution {
public int maxCandies(int[] status, int[] candies, int[][] keys, int[][] containedBoxes, int[] initialBoxes) {
boolean[] visited = new boolean[status.length];
boolean[] haveKey = new boolean[status.length];
// init
Deque<Integer> q = new ArrayDeque<>();
for (int i : initialBoxes) {
q.add(i);
visited[i] = true;
for (int j : keys[i]) haveKey[j] = true;
}
// break condition: found no key & box == hopeless
boolean hope = true;
int ans = 0;
while (hope) {
int sz = q.size();
hope = false;
while (sz-- > 0) {
int i = q.poll();
if (status[i] == 1 || (status[i] == 0 && haveKey[i])) { // 1. opened or can open
for (int k : keys[i]) {
if (haveKey[k]) continue; // useless key
haveKey[k] = true; // get keys
hope = true;
}
for (int b : containedBoxes[i]) {
if (visited[b]) continue;
q.add(b); // get boxes
visited[b] = true;
hope = true;
}
ans += candies[i];
}
else { // 2. closed or can't open
q.add(i);
}
}
}
return ans;
}
}
풀이 해설
지문의 내용에 따라 그대로 조건을 구현해서 bfs로 풀이하는 문제이다.
📦 보유 중인 박스는 큐로 저장하기
Deque<Integer> q = new ArrayDeque<>();
for (int i : initialBoxes) {
q.add(i);
visited[i] = true;
for (int j : keys[i]) haveKey[j] = true;
}
initialBoxes
에 주어진 시작 박스들을 전부 큐에 넣고, 중복 삽입하지 않도록 방문 처리한다.
그리고 보유중인 박스에 대한 모든 key들도 보유 처리한다.
haveKey
는 그냥 쉽게 생각해서 key에 대한 boolean 타입 visited이다.
이걸로 keys[i]
에 대한 방문 판별도 하고 보유 판별도 한다.
key도 방문 처리하는 이유는 이미 예전에 2번 키 사용했었는데 다른 상자에서 또 2번 키 나왔다고 희망이 생기면 안되기 때문이다.
"언제까지 희망고문 할건데"
// break condition: found no key & box == hopeless
boolean hope = true;
int ans = 0;
while (hope) {
int sz = q.size();
hope = false;
while (sz-- > 0) {
...
}
문제 풀이에 가장 시간을 투자한 부분인데, bfs를 돌리다가 어느 기준으로 while을 빠져나올지 고민되었다.
왜냐하면 큐의 박스들을 다 스캔해서 key나 containedBox를 찾아보아도 아무 진척이 없을 때
이는 더이상의 탐색이 의미없어 while문을 종료할 타이밍이지만,
여전히 큐에는 박스들이 남아있기 때문이다. (즉, !q.isEmpty()
사용 불가)
따라서 큐의 박스들을 한차례 다 스캔하는 것을 1 wave로 기준잡아 wave당 큐 size만큼 순회했고
size만큼 순회하는동안 쓸만한 key나 containedBox를 찾았다면 hope
를 true로 설정해서 bfs라는 희망고문을 계속하도록 로직을 구성했다.
메모
- while문 구성만 약간의 생각이 필요한 부분이고 다른건 무난한 난이도이다.
- NextLeet의 존재를 알게되었다. 여행 가기 전 미리 풀어두면 좋을듯?