👀 문제 설명
N 개의 막대 기둥이 일렬로 세워져 있다. 기둥들의 폭은 모두 1 m이며 높이는 다를 수 있다. 이 기둥들을 이용하여 양철로 된 창고를 제작하려고 한다. 창고에는 모든 기둥이 들어간다. 이 창고의 지붕을 다음과 같이 만든다.
- 지붕은 수평 부분과 수직 부분으로 구성되며, 모두 연결되어야 한다.
- 지붕의 수평 부분은 반드시 어떤 기둥의 윗면과 닿아야 한다.
- 지붕의 수직 부분은 반드시 어떤 기둥의 옆면과 닿아야 한다.
- 지붕의 가장자리는 땅에 닿아야 한다.
- 비가 올 때 물이 고이지 않도록 지붕의 어떤 부분도 오목하게 들어간 부분이 없어야 한다.
그림 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 |