포스트

14719 빗물

고이는 빗물의 총량을 구하는 문제

시뮬레이션, 구현 문제

https://www.acmicpc.net/problem/14719

1. 문제


간단 설명

rainwater

2차원 세계에 블록이 쌓여있을때, 비가 오면 사이에 빗물이 고인다

고이는 빗물의 총량을 구하는 문제

2. 문제 분석


알고리즘

내 풀이

1
2
3
4
5
1. 입력받기
2. y = 0부터 차례로 내려가면서 블록이 있는지 확인한다
3. 블록이 있다면 현재 X좌표를 기록해두고, 오른쪽으로 자신과 동등한 높이가 있는지 확인한다
4. 자신과 동등한 높이가 있다면, 빗물이 고일 수 있으므로,    
    X좌표과 동등한 좌표의 위치 사이의 블럭만큼 고인 물의 양을 기록에 추가한다

다른 풀이. 1차원 배열 이용

1
2
3
4
1. X=0 부터 시작해서 W까지 순회한다
2. 현재블럭 기준으로 왼쪽 중 제일 큰값과, 오른쪽 기준 제일 큰 기둥을 찾는다
3. 둘 중 작은 기둥을 선택한다 (물이 고이기 위해 )
4. 선택한 작은 기둥 - 현재 기둥의 높이만큼 결과에 더해준다

주의점

  • 입력받을때, 블럭을 아래부터 쌓을것인지, 위에서부터 쌓을것인지 고려해야함
    • 둘다 문제를 해결하는데 상관은 없음. 그러나 디버깅 가시성을 위해서 아래서부터 쌓았음
  • 블록 좌표 X와, 동등한 높이의 좌표를 찾는 과정에서, 바로 옆에 블럭이 있다면?

필요변수

가로, 세로 H, W

2차원 배열을 저장할 map[H][W]

빗물 총량 total

그 외 계산을 위한 변수들

3. 소스코드


2차원 배열 이용 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>

using namespace std;

int H, W;
int map[501][501];

int main() {
	freopen_s(new FILE*, "input.txt", "r", stdin);
	cin >> H >> W;
	for (int x = 0; x < W; x++) {
		int num; cin >> num;
		for (int y = H-1; y >= H-num; y--) {
			map[y][x] = 1;
		}
	}

	int height = 0;
	int total = 0;
	while (height < H) {
		for (int x = 0; x < W; x++) {
			// 최대 높이가 발견된 경우
			if (map[height][x] == 1) {
				// 자기와 같은 높이가 있는지 확인한다
				for (int i = x+1; i < W; i++) {
					if (map[height][i] == 1) {
						total += i - x - 1;
						break;
					}
				}

			}
		}
		height++;
	}

	cout << total;

	return 0;
}

1차원 투포인터 이용 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>

using namespace std;

int map[501];
int h, w;

// 현재 칸에 저장될 물을 구하는 함수
// 제일 왼쪽과 오른쪽에는 물이 고일 수 없으므로, 
// idx : (1,w-1)
int water(int idx) {
	int leftIdx = 0, rightIdx = w - 1;

	// 왼쪽에서 가장 큰 기둥 탐색 (0~idx)
	for (int i = 0; i < idx; i++) {
		if (map[i] > map[leftIdx]) {
			leftIdx = i;
		}
	}

	// 오른쪽에서 가장 큰 기둥 탐색 (idx~w-1)
	for (int i = idx; i < w - 1; i++) {
		if (map[i] > map[rightIdx]) {
			rightIdx = i;
		}
	}

	// 둘 중 작은 기둥 선택
	int k = min(map[leftIdx], map[rightIdx]);

	// 현재 칸에 물이 얼마나 저장될지 계산
	int res = k - map[idx];
	if (res < 0) res = 0;	// 자기보다 큰 기둥이 없어서 음수가 나오는 경우 0으로 처리

	return res;
}

int main() {
	freopen_s(new FILE*, "input.txt", "r", stdin);

	cin >> h >> w;

	for (int i = 0; i < w; i++) {
		cin >> map[i];
	}

	int total = 0;
	for (int i = 0; i < w - 1; i++) {
		total += water(i);
	}

	cout << total;

	return 0;
}

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.