📕알고리즘 문제/📝Baekjoon

[백준] 골드5 : (15989) 빗물

주으기 2025. 2. 6. 09:13
728x90
반응형

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

 

이 문제 구현의 핵심은, 앞에서 한 번, 뒤에서 한 번 계산하는 것이다.

 

먼저, 앞에서 끝까지 계산한다.

  • 시작 위치가 0이 아닌, 3이니 시작 위치를 3으로 저장한다.
  • 다음 땅의 위치를 계속 보며, 3보다 크거나 같은 땅이 나올 때까지 이동한다.
  • 3보다 크거나 같지 않은 땅들은 모두 빗물이 담길 수 있는 땅이니, 저장한다.

 

  • 3보다 크거나 같은 위치가 나왔다.
  • 그러면, 이동안 빗물이 담길 수 있는 땅들을 순회하며, 빗물을 담아준다.
    • 처음 시작 위치(3)에서 저장된 땅의 위치(1, 2)를 뺀 값을 정답에 더한다.
  • 이제, 계산을 마치고 시작 위치를 현재 위치로 갱신한다. (여기서부터 다시 계산 시작)

 

  • 다음으로, 3에서 시작하면 4를 만나게 된다.
  • 앞서 했던 과정을 반복한다. (어차피 빗물이 담긴 땅이 없음)
  • 시작 위치가 4로 갱신되고, 또 순회를 시작한다.
  • 마지막까지 다 이동했지만, 4보다 크거나 같은 땅이 없기 떄문에, 계산을 종료한다.

 

 

이 계산 방법으로 처음부터 끝까지 계산을 했다.

마지막을 보면 높이가 2이기 때문에, 빗물이 담길 수 있다.

이 떄문에 반대쪽에서 다시 계산을 시작하는 것이다.

처음 계산에서 마지막으로 높이가 가장 높았던 땅의 인덱스를 저장해 뒀다가, 이를 기점으로 반대쪽에서 다시 계산을 한다.

 

그러면, 2에서 시작해서 4에서 끝난다.

중간에 빗물이 담길 수 있는 (1, 1)을 계산해서 총합에 더한다.

 

 

최종적으로, 다음과 같이 앞쪽과 뒤쪽의 계산을 통해 총합을 구한다.

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

void Func(const vector<int>& Block, int& Answer, int Start, int& Index, bool Flag)
{
	queue<int> Save;	// 빗물이 담길 땅의 높이
	int Cur = 0;		// 현재 빗물을 담고 있는 땅의 높이

	int Ret = -1;		// 마지막으로 본 가장 높은 위치의 인덱스
						// 뒤에서 계산할 때, 이 인덱스를 기점으로 잡음

	for (int i = Start; Flag ? i < Index : i >= Index; Flag ? ++i : --i)
	{
		// 현재 빗물을 담고 있는 땅의 높이가 0이고, 현재 땅의 높이가 0이 아닌 경우 (현재 땅의 높이가 0이면 어차피 빗물을 못 담기 떄문에)
		if (Cur == 0 && Block[i] != 0)
		{
			Cur = Block[i];	// 현재 빗물을 담고 있는 땅의 높이를 현재 땅의 높이로 초기화
			Ret = i;		// 마지막으로 본 가장 높은 위치의 인덱스 저장
			continue;
		}

		// 현재 빗물을 담고 있는 땅의 높이보다 현재 땅의 높이가 같거나 큰 경우
		if (Cur <= Block[i])
		{
			// 두 땅의 위치 사이의 있는 
			while (!Save.empty())
			{
				Answer += Cur - Save.front();
				Save.pop();
			}
			Cur = Block[i];
			Ret = i; // 마지막으로 본 가장 높은 위치의 인덱스 저장
		}
		// 빗물이 담길 땅이니, 위치 저장
		else Save.push(Block[i]);
	}

	Index = Ret;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int Y, X, Answer = 0;
	cin >> Y >> X;

	vector<int> Block(X);
	for (int i = 0; i < X; ++i)
		cin >> Block[i];

	int Index = X;
	Func(Block, Answer, 0, Index, true);		// 시작 ~ 끝
	Func(Block, Answer, X - 1, Index, false);	// 끝 ~ 마지막으로 본 가장 높은 위치의 인덱스

	cout << Answer << "\n";
}

 

 

 

 

 

 

728x90
반응형