빗물 (백준 14719)

2024. 4. 17. 19:19알고리즘

문제

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

🚀문제 접근

너비를 완전탐색하면서 해당 위치에 빗물이 얼만큼 고여있을 수 있는지 구하면 된다.

1. 블록이 쌓인 높이를 순회한다.

2. 해당 위치에서 왼쪽에 있는 블록들 중 가장 길이가 큰 블록(leftMax)과 오른쪽에 있는 블록들 중 가장 길이가 큰 블록(rightMax)을 구한다.

    2-1. 만약 왼쪽 값을 참조할 수 없거나 오른쪽 값을 참조할 수 없는 경우에는 continue

3. leftMax와 rightMax 중 최솟값을 구한다.(min)

4. min에서 현재 위치의 블록 길이를 뺀다.

    4-1. 만약 음수가 나오면 continue

5. 뺀 결과값을 ret에 누적한다.

 

빗물이 고여있기 위해선 현재 위치의 양옆에 자신보다 길이가 긴 블록이 반드시 있어야하며 고여있는 양은 양쪽에서 구한 최대길이값 중 작은 값에서 현재 위치의 블록 길이를 뺀 값이 나온다.

🛠코드

let [a, blocks] = require('fs').readFileSync(0).toString().trim().split('\n');
let [h, w] = a.split(' ').map(Number);
blocks = blocks.split(' ').map(Number);

function solution() {
  let ret = 0;
  for (let i = 0; i < blocks.length; i++) {
    let cur = blocks[i];
    if (i - 1 === -1 || i + 1 === blocks.length) continue;
    let leftMax = Number.MIN_SAFE_INTEGER;
    let rightMax = Number.MIN_SAFE_INTEGER;
    for (let j = i - 1; j >= 0; j--) {
      leftMax = Math.max(leftMax, blocks[j]);
    }
    for (let k = i + 1; k < blocks.length; k++) {
      rightMax = Math.max(rightMax, blocks[k]);
    }
    let min = Math.min(leftMax, rightMax);
    if (min - cur < 0) continue;
    ret += min - cur;
  }

  return ret;
}

console.log(solution());

 

'알고리즘' 카테고리의 다른 글

0 만들기 (백준 7490)  (1) 2024.04.18
빌런 호석 (백준 22251)  (0) 2024.04.18
문자열 게임 2 (백준 20437)  (0) 2024.04.17
컨베이어 벨트 위의 로봇 (백준 20055)  (0) 2024.04.17
로봇 청소기 (백준 14503)  (1) 2024.04.16