백준 14719번 (빗물, C++, Simulation) [BAEKJOON]

빗물

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

시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초256 MB106645888465955.770%

문제

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

비는 충분히 많이 온다. 고이는 빗물의 총량은 얼마일까?

입력

첫 번째 줄에는 2차원 세계의 세로 길이 H과 2차원 세계의 가로 길이 W가 주어진다. (1 ≤ H, W ≤ 500)

두 번째 줄에는 블록이 쌓인 높이를 의미하는 0이상 H이하의 정수가 2차원 세계의 맨 왼쪽 위치부터 차례대로 W개 주어진다.

따라서 블록 내부의 빈 공간이 생길 수 없다. 또 2차원 세계의 바닥은 항상 막혀있다고 가정하여도 좋다.

출력

2차원 세계에서는 한 칸의 용량은 1이다. 고이는 빗물의 총량을 출력하여라.

빗물이 전혀 고이지 않을 경우 0을 출력하여라.

예제 입력 1

4 4
3 0 1 4

예제 출력 1

5

예제 입력 2

4 8
3 1 2 3 4 1 1 2

예제 출력 2

5

예제 입력 3

3 5
0 0 0 2 0

예제 출력 3

0

출처

University > 충남대학교 > 생각하는 프로그래밍 대회  D번

  • 문제를 만든 사람: isku

알고리즘 분류


아래서부터 블록과 블록 사이에 공간을 카운트하여 고여있는 빗물의 칸을 계산할 생각

좌/우 를 확인하면서 빈공간을 체크하면 좋을 것 같다.

입력 확인 코드

#include <iostream>

using namespace std;

// 가로, 세로의 길이는 최대치가 500
constexpr auto MAX = 500;

// 0 빈공간, 1 블록
int map[MAX][MAX];

// 가로 / 세로
int H, W, tempOne, tempTwo;

// 빗물의 개수
int rainwaterCnt = 0;

bool debugbool = true;

// 시각적인 디버깅을 위한 함수
void VisualDebug()
{
	cout << "\n";
	for (int i = 0; i < W; i++)
	{
		for (int j = 0; j < H; j++)
		{
			cout << map[i][j] << " ";
		}
		cout << "\n";
	}
}

// 문제의 입력을 받는 함수
void ReceiveInput()
{
	cin >> H >> W;

	tempTwo = W;

	for (int i = 0; i < tempTwo; i++)
	{
		cin >> tempOne;
		for (int j = 0; j < tempOne; j++)
		{
			map[i][j] = 1;
		}
	}
	
}

// 초기화를 진행하는 함수
void Initialization()
{
	for (int i = 0; i < MAX; i++)
	{
		for (int j = 0; j < MAX; j++)
		{
			map[i][j] = 0;
		}
	}
}

int main()
{
	Initialization();
	ReceiveInput();
	if (debugbool) { VisualDebug(); }

	return 0;
}

문제의 힌트와 배열이 다른 것에 주의

통과된 코드

#include <iostream>

using namespace std;

// 가로, 세로의 길이는 최대치가 500
constexpr auto MAX = 500;

// 0 빈공간, 1 블록
int map[MAX][MAX];

// 가로 / 세로
int H, W, tempOne;

// 첫 블록을 마킹하는 bool 값
bool leftRight;

// 빗물의 개수
int rainwaterCnt;

bool debugbool = false;

// 시각적인 디버깅을 위한 함수
void VisualDebug()
{
	cout << "\n";
	for (int i = 0; i < W; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			cout << map[i][j] << " ";
		}
		cout << "\n";
	}
}

// 문제의 입력을 받는 함수
void ReceiveInput()
{
	cin >> H >> W;

	for (int i = 0; i < W; i++)
	{
		cin >> tempOne;
		for (int j = 0; j < tempOne; j++)
		{
			map[i][j] = 1;
		}
	}
}

// 초기화를 진행하는 함수
void Initialization()
{
	for (int i = 0; i < MAX; i++)
	{
		for (int j = 0; j < MAX; j++)
		{
			map[i][j] = 0;
		}
	}
}

// 빗물을 카운트 합니다.
void CountRainwater()
{
	rainwaterCnt = 0;

	// 아래부터 위로 검색
	for (int i = 0; i < H; i++)
	{
		leftRight = false;
		tempOne = 0;

		for (int j = 0; j < W; j++)
		{
			if (map[j][i] == 1)
			{
				if (!leftRight)
				{
					// 좌에서 우로 검색하다 처음 블록을 찾으면 마킹
					leftRight = true;
					tempOne = 0;
				}
				else
				{
					// 마킹이 되어있는 상태에서 블록을 찾으면 
					// 빈공간을 카운트하는 tempOne을 결과값에 더해준다.
					// 그리고 0으로 초기화
					rainwaterCnt += tempOne;
					tempOne = 0;
				}

			}
			else if (map[j][i] == 0)
			{
				// 해당 위치가 빈공간이고 첫 블록 마킹이 되어있다면 
				// 빈공간을 카운트하는 tempOne을 하나 늘려줍니다.
				if (leftRight)
				{
					tempOne++;
				}

			}
		}
	}
}

int main()
{
	Initialization();
	ReceiveInput();
	CountRainwater();
	if (debugbool) { VisualDebug(); }
	// 결과를 출력합니다.
	cout << rainwaterCnt;
	return 0;
}

처음에 생각한 간단한 로직으로 코드를 구현하고 통과한 문제입니다.

이 문제를 해결하는 방법은 다양할 것 같습니다.

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤