본문 바로가기

숨막히는 알고말고/문제 풀이

[Baekjoon] 창고 다각형

👀 문제 설명

문제

N 개의 막대 기둥이 일렬로 세워져 있다. 기둥들의 폭은 모두 1 m이며 높이는 다를 수 있다. 이 기둥들을 이용하여 양철로 된 창고를 제작하려고 한다. 창고에는 모든 기둥이 들어간다. 이 창고의 지붕을 다음과 같이 만든다.

  1. 지붕은 수평 부분과 수직 부분으로 구성되며, 모두 연결되어야 한다.
  2. 지붕의 수평 부분은 반드시 어떤 기둥의 윗면과 닿아야 한다.
  3. 지붕의 수직 부분은 반드시 어떤 기둥의 옆면과 닿아야 한다.
  4. 지붕의 가장자리는 땅에 닿아야 한다.
  5. 비가 올 때 물이 고이지 않도록 지붕의 어떤 부분도 오목하게 들어간 부분이 없어야 한다.

그림 1은 창고를 옆에서 본 모습을 그린 것이다. 이 그림에서 굵은 선으로 표시된 부분이 지붕에 해당되고, 지붕과 땅으로 둘러싸인 다각형이 창고를 옆에서 본 모습이다. 이 다각형을 창고 다각형이라고 하자.

그림1 . 기둥과 지붕(굵은 선)의 예

창고 주인은 창고 다각형의 면적이 가장 작은 창고를 만들기를 원한다. 그림 1에서 창고 다각형의 면적은 98 ㎡이고, 이 경우가 가장 작은 창고 다각형이다.

기둥들의 위치와 높이가 주어질 때, 가장 작은 창고 다각형의 면적을 구하는 프로그램을 작성하시오.

 

입력

첫 줄에는 기둥의 개수를 나타내는 정수 N이 주어진다. N은 1 이상 1,000 이하이다. 그 다음 N 개의 줄에는 각 줄에 각 기둥의 왼쪽 면의 위치를 나타내는 정수 L과 높이를 나타내는 정수 H가 한 개의 빈 칸을 사이에 두고 주어진다. L과 H는 둘 다 1 이상 1,000 이하이다.

 

출력

첫 줄에 창고 다각형의 면적을 나타내는 정수를 출력한다.

 

예제 입력 1

7

2 4

11 4

15 8

4 6

5 3

8 10

13 6

 

예제 출력 1

98

✍🏻풀이

BOJ 14719 빗물 문제와 유사하게 풀면 된다.

 

1. 가장 높은 기둥을 구한다. (maxH)

 2-1. maxH 기준 왼쪽에서, 가장 높은 기둥(leftMax)을 storage[beginL]로 두고,

    현재 위치의 기둥이 leftMax보다 작다면, answer에 leftMax를 더한다.

    현재 위치의 기둥이 leftMax보다 크다면, leftMax 값을 현재 위치의 기둥으로 바꿔준 후, answer에 leftMax를 더한다.

 2-2. maxH 기준 오른쪽에서, 가장 높은 기둥(rightMax)을 storage[endL]로 두고,

    현재 위치의 기둥이 rightMax보다 작다면, answer에 rightMax를 더한다.

    현재 위치의 기둥이 rightMax보다 크다면, rightMax 값을 현재 위치의 기둥으로 바꿔준 후, answer에 rightMax를 더한다.

 

코드

#include <stdio.h>
#include <iostream>

#define MAX 1001

using namespace std;

int storage[MAX]; // 기둥 정보를 갖는 배열

/**
 1. 가장 높은 기둥을 구한다. (maxH)
 2-1. maxH 기준 왼쪽에서, 가장 높은 기둥(leftMax)을 storage[beginL]로 두고,
    현재 위치의 기둥이 leftMax보다 작다면, answer에 leftMax를 더한다.
    현재 위치의 기둥이 leftMax보다 크다면, leftMax 값을 현재 위치의 기둥으로 바꿔준 후, answer에 leftMax를 더한다.
 2-2. maxH 기준 오른쪽에서, 가장 높은 기둥(rightMax)을 storage[endL]로 두고,
    현재 위치의 기둥이 rightMax보다 작다면, answer에 rightMax를 더한다.
    현재 위치의 기둥이 rightMax보다 크다면, rightMax 값을 현재 위치의 기둥으로 바꿔준 후, answer에 rightMax를 더한다.
 */
int main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL); cout.tie(NULL);
    
    int N;
    cin >> N;
    
    int beginL = 1000; // 가장 왼쪽에 있는 기둥의 위치를 구한다.
    int endL = 0; // 가장 오른쪽에 있는 기둥의 위치를 구한다.
    int maxH = 0;
    int maxIndex = -1;
    for (int i = 0; i < N; i++) {
        int L, H;
        cin >> L >> H;
        
        storage[L] = H; // L 위치에 있는 높이가 H이다.
        
        if (beginL > L)
            beginL = L;
        
        if (endL < L)
            endL = L;
        
        // 1. 가장 높은 기둥과 그 위치를 구한다.
        if (maxH < H) {
            maxH = H;
            maxIndex = L;
        }
    }
    
    int answer = maxH; // answer의 초기값은 maxH이다.
    // 2-1. maxH 기준 왼쪽
    int leftMax = storage[beginL]; // leftMax의 초기값을 storage[beginL]로 준다.
    if (beginL != maxIndex) // beginL이 maxIndex일 경우, maxH가 두 번 더해지므로 beginL이 maxIndex가 아닐 경우에만 더해준다.
        answer += leftMax;
    
    for (int i = beginL + 1; i < maxIndex; i++) { // maxIndex는 포함하지 않는다.
        if (leftMax <= storage[i]) {
            leftMax = storage[i];
        }
        answer += leftMax;
    }
    
    // 2-2. maxH 기준 오른쪽
    int rightMax = storage[endL];
    if (endL != maxIndex) // rightMax의 초기값을 storage[beginL]로 준다.
        answer += rightMax; // endL이 maxIndex일 경우, maxH가 두 번 더해지므로 endL이 maxIndex가 아닐 경우에만 더해준다.
    
    for (int i = endL - 1; i > maxIndex; i--) { // maxIndex는 포함하지 않는다.
        if (rightMax <= storage[i]) {
            rightMax = storage[i];
        }
        answer += rightMax;
    }
    
    cout << answer << "\n";
    
    return 0;
}

'숨막히는 알고말고 > 문제 풀이' 카테고리의 다른 글

[Baekjoon] 경사로  (0) 2021.03.25
[Baekjoon] 녹색 옷 입은 애가 젤다지?  (0) 2021.03.24
[Baekjoon] 빗물  (0) 2021.03.24
[Baekjoon] 보물  (0) 2021.03.18
[Baekjoon] 연결 요소의 개수  (0) 2021.03.16