https://www.acmicpc.net/problem/14719
#include <iostream>
#include <vector>
using namespace std;
vector<int> blk;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int h, w;
int ans = 0;
cin >> h >> w;
blk.resize(w);
for (int i = 0; i < w; i++) {
cin >> blk[i];
}
for (int i = 1; i <= h; i++) {
//고이는 물의 시작 지점
int s = -1;
bool isStart = false;
//blk[j]<i: 빈 공간
//blk[j]>=i: 블럭 공간
for (int j = 0; j < w; j++) {
if(isStart && blk[j] >= i) {
ans += j - s - 1;
isStart = false;
}
if (!isStart && blk[j] >= i) {
if (j != w - 1 && blk[j + 1] < i) {
s = j;
isStart = true;
}
}
}
}
cout << ans;
return 0;
}
1. 문제
h*w 크기의 2차원 세계가 있다. 이 세계에서 비가 충분히 오면 블럭 사이에 비가 고인다. 1*1 크기에 1의 빗물이 채워진다고 할 때, 빗물의 총량을 출력하라. 단, 빗물이 고이지 않을 경우 0을 출력하라.
2. 풀이
4 8
3 1 2 3 4 1 1 2
이런 입력이 주어졌다고 하면 오른쪽 그림대로 빗물이 차 5가 출력될 것이다. 이를 높이 단위로 잘라서 보면 다음과 같다.
즉, 어떤 빈 공간이 두 블럭 사이에 둘러싸여 있을 경우 빗물이 찰 수 있다. 이를 아이디어 삼아 문제를 풀어보자.
for (int i = 1; i <= h; i++) {
//고이는 물의 시작 지점
int s = -1;
bool isStart = false;
//blk[j]<i: 빈 공간
//blk[j]>=i: 블럭 공간
for (int j = 0; j < w; j++) {
if(isStart && blk[j] >= i) {
ans += j - s - 1;
isStart = false;
}
if (!isStart && blk[j] >= i) {
if (j != w - 1 && blk[j + 1] < i) {
s = j;
isStart = true;
}
}
}
}
각 빗물이 들어갈 공간은 시작과 끝이 있다. 이 조합이 완성된다면 이 위치에는 빗물이 찰 수 있다. 하나씩 살펴보자
if (!isStart && blk[j] >= i) {
if (j != w - 1 && blk[j + 1] < i) {
s = j;
isStart = true;
}
}
시작점이 정해지지 않은 상태에서 블럭이 있고, 그 다음이 빈 공간이면 이는 시작지점이 될 수 있다.
if(isStart && blk[j] >= i) {
ans += j - s - 1;
isStart = false;
}
시작점이 정해진 상태에서 빈 공간이 아닌 블럭을 만나면 이를 끝 지점으로 정할 수 있다. 이 사이의 빗물의 양은 양 끝점이 포함되지 않으므로 (끝 지점)-(시작 지점)-1이다.
어떤 공간의 끝 지점인 동시에 다음 지점의 시작점인 경우가 존재할 수 있으므로 끝 지점 여부를 먼저 확인한다.
연산이 끝나고 총 빗물의 양을 출력하면 정답을 구할 수 있다.
'Coding Test' 카테고리의 다른 글
백준 1368 물대기 (C++) (1) | 2024.07.27 |
---|---|
백준 22943 수 (C++) (0) | 2024.07.26 |
백준 20207 달력 (C++) (2) | 2024.07.23 |
백준 20164 홀수 홀릭 호석 (C++) (3) | 2024.07.22 |
백준 13019 A를 B로 (C++) (1) | 2024.07.21 |