본문으로 바로가기

[BOJ 14719] 빗물 (C++)

category Algorithms/Implementation 2021. 11. 4. 13:54

빗물 (Gold 5)

문제

전체 문제 보기

 

14719번: 빗물

첫 번째 줄에는 2차원 세계의 세로 길이 H과 2차원 세계의 가로 길이 W가 주어진다. (1 ≤ H, W ≤ 500) 두 번째 줄에는 블록이 쌓인 높이를 의미하는 0이상 H이하의 정수가 2차원 세계의 맨 왼쪽 위치

www.acmicpc.net

접근법

이번 문제는 가장 왼쪽에서 → 가장 큰 블록 까지, 그리고 가장 오른쪽 → 가장 큰 블록까지 탐색을 통해서 빗물의 양을 구할 수 있습니다. 따라서 전체 가로의 크기 \(W\)일 때 \(O(W)\) 시간 안에 계산을 마칠 수 있습니다.

탐색방법은 복잡하지 않기 때문에 코드를 통해서 참고해 주세요.

전체 코드

#include <iostream>
#include <vector>
#include <algorithm>
#define endl '\n'
using namespace std;

void InputData(int& H, int& W, vector<int>& blocks)
{
    cin >> H >> W;
    blocks.resize(W);
    for (int i = 0; i < W; ++i)
    {
        cin >> blocks[i];
    }
}
int Solve(const int H, const int W, const vector<int>& blocks)
{
    int retval{};
    const auto maxIter = max_element(blocks.begin(), blocks.end());
    const int maxIdx = distance(blocks.begin(), maxIter);

    // 왼쪽에서 오른쪽으로 탐색. (시작점에서 가장큰 블록이 있는곳 까지)
    int left = blocks.front();
    int temp{};
    for (int i = 1; i <= maxIdx; i++)
    {
        if (left > blocks[i])
        {
            temp += left - blocks[i];
        }
        else
        {
            retval += temp;
            left = blocks[i];
            temp = 0;
        }
    }
    // 오른쪽에서 왼쪽으로 탐색. (시작점에사 가장 큰 블록이 있는곳 까지)
    int right = blocks.back();
    temp = 0;
    for (int i = W - 2; i >= maxIdx; i--)
    {
        if (right > blocks[i])
        {
            temp += right - blocks[i];
        }
        else
        {
            retval += temp;
            right = blocks[i];
            temp = 0;
        }
    }

    return retval;
}
int main()
{
    //입출력 성능향상을 위한 설정
    ios_base::sync_with_stdio(false);
    cout.tie(NULL);
    cin.tie(NULL);

    int H, W; // (1 ≤ H, W ≤ 500)
    vector<int> blocks;
    InputData(H, W, blocks);
    int answer = Solve(H, W, blocks);
    cout << answer;
    return 0;
}