🔗 14719번 : 빗물
● Java 풀이
● 시간 제한 1초
● 메모리 제한 256 MB
✅ 문제
2차원 세계에 블록이 쌓여있다. 비가 오면 블록 사이에 빗물이 고인다.
비는 충분히 많이 온다. 고이는 빗물의 총량은 얼마일까?
✅ 테스트 케이스
// input
4 8
3 0 1 2 1 2 3 4
//answer
9
// input
500 3
1 2 500
// answer
0
// input
500 5
500 2 1 1 2
//answer
2
// input
500 4
0 2 1 500
// answer
1
// input
500 3
500 2 500
// answer
498
// input
500 500
500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1 500 1
// answer
124251
// input
3 6
5 4 1 3 1 2
// answer
3
✅ 풀이
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
st.nextToken(); // 블록의 최대 높이
int W = Integer.parseInt(st.nextToken()); // 블록 정렬 개수 (너비)
st = new StringTokenizer(br.readLine());
PriorityQueue<Integer> pq = new PriorityQueue<>(); // 높이를 비교할 Priority Queue 생성
int blockHeight, maxHeight = 0; // 현재 확인할 블록 높이, 지금까지 찾은 블록 중 최대 높이
int count = 0; // 지금까지 채운 물의 칸 수
for (int i = 0; i < W; i++) {
blockHeight = Integer.parseInt(st.nextToken()); // 다음 블록 높이 받기
if (maxHeight <= blockHeight) { // 현재 블록이 최대 높이와 같거나 최대 높이보다 클 경우
while (!pq.isEmpty() && pq.peek() <= maxHeight) { // 지금까지의 낮은 높이들을
count += maxHeight - pq.poll(); // 이전의 최대 높이만큼 채우기
}
maxHeight = blockHeight; // 최대 높이를 현재 블록 높이로 변경 (이전 블록은 다시 돌아보지 않음)
} else { // 현재 블록이 최대 높이보다 낮을 경우
while (!pq.isEmpty() && pq.peek() < blockHeight) { // 현재 높이보다 낮은 높이가 있을 때
count += blockHeight - pq.poll(); // 블록 높이를 현재 높이로 채우기
pq.add(blockHeight); // 물 더하기
}
}
pq.add(blockHeight); // 현재 블록 삽입
}
System.out.println(count);
}
}
이 문제는 최대 높이가 나왔을 경우, 이전의 블록들을 더이상 돌아볼 필요가 없다는 것을 기억해야 한다.
탐색한 최대 높이보다 더 큰 높이가 나왔을 경우 그 이전 블록들은 물이 더이상 채워질 수 없기 때문이다.
블록이 이와 같이 주어졌을 때, 2 높이 블록의 높이를 받을 때의 Priority Queue 는 {1, 3}이다.
2 높이 블록은 최대 높이인 3 높이 블록보다 낮으므로, Priority Queue에서 자신보다 낮은 수가 존재하지 않을 때까지 물을 채우고 끝낸다. {2, 2, 3}
하지만 최대 높이인 3 높이보다 높은 블록이 나타났을 경우는 어떨까?
이후 나타난 3 높이 블록은 최대 높이인 3 높이 블록과 같으므로, Priority Queue에서 이전 최대 높이보다 낮은 수가 존재하지 않을 때까지 물을 채우되, 물을 채운 블록들은 더이상 신경쓰지 않는다.
그 이유는 아래에 제시한 그림과 같다.
이후 블록이 어떤 높이가 와도, 마지막 최대 높이 이전의 블록에 채울 수 있는 물은 그 공간 내에 최대 높이를 넘을 수 없기 때문이다. 중간의 3 높이 블록이 4 높이로 바뀌었다고 가정해보자. 그럼에도 그 공간 내에 채울 수 있는 물은 이전 최대 높이인 첫 번째 블록, 3 높이인 것은 마찬가지이다.
이를 고려하며 문제를 풀면 반복 횟수를 줄일 수 있다.
'알고리즘 및 데이터 구조 > 백준' 카테고리의 다른 글
[백준] 12110번 2048 (Easy) (Java) (0) | 2024.04.06 |
---|---|
[백준] 2011번 : 암호코드 (Java) (0) | 2024.03.26 |
[백준] 11000번 : 강의실 배정 (Java) (0) | 2024.03.24 |
[백준] 4386번 : 별자리 만들기 (Java) (3) | 2024.03.19 |
[백준] 17135번 : 캐슬 디펜스 (Java) (2) | 2024.03.18 |