문제
N 개의 막대 기둥이 일렬로 세워져 있다. 기둥들의 폭은 모두 1 m이며 높이는 다를 수 있다. 이 기둥들을 이용하여 양철로 된 창고를 제작하려고 한다. 창고에는 모든 기둥이 들어간다. 이 창고의 지붕을 다음과 같이 만든다.
- 지붕은 수평 부분과 수직 부분으로 구성되며, 모두 연결되어야 한다.
- 지붕의 수평 부분은 반드시 어떤 기둥의 윗면과 닿아야 한다.
- 지붕의 수직 부분은 반드시 어떤 기둥의 옆면과 닿아야 한다.
- 지붕의 가장자리는 땅에 닿아야 한다.
- 비가 올 때 물이 고이지 않도록 지붕의 어떤 부분도 오목하게 들어간 부분이 없어야 한다.
그림 1은 창고를 옆에서 본 모습을 그린 것이다. 이 그림에서 굵은 선으로 표시된 부분이 지붕에 해당되고, 지붕과 땅으로 둘러싸인 다각형이 창고를 옆에서 본 모습이다. 이 다각형을 창고 다각형이라고 하자.

그림1 . 기둥과 지붕(굵은 선)의 예
창고 주인은 창고 다각형의 면적이 가장 작은 창고를 만들기를 원한다. 그림 1에서 창고 다각형의 면적은 98 ㎡이고, 이 경우가 가장 작은 창고 다각형이다.
기둥들의 위치와 높이가 주어질 때, 가장 작은 창고 다각형의 면적을 구하는 프로그램을 작성하시오.
입력
첫 줄에는 기둥의 개수를 나타내는 정수 N이 주어진다. N은 1 이상 1,000 이하이다. 그 다음 N 개의 줄에는 각 줄에 각 기둥의 왼쪽 면의 위치를 나타내는 정수 L과 높이를 나타내는 정수 H가 한 개의 빈 칸을 사이에 두고 주어진다. L과 H는 둘 다 1 이상 1,000 이하이다.
출력
첫 줄에 창고 다각형의 면적을 나타내는 정수를 출력한다.
가장 큰 높이를 기준으로 두 구간으로 나누어 검사한다.
처음부터 가장 큰 높이까지는 높이가 큰 막대를 만날 때마다 높이를 업데이트하고, 낮은 경우에는 무시한다.
가장 큰 높이부터 마지막 막대까지는 내림차순이어야 하는데, 오목한 부분은 피해야하기 때문에 마지막 index부터 검사하여 다시 오름차순으로 높이를 업데이트 한다.
package Silver.s2;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;
public class BOJ_2304_창고다각형 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
ArrayList<Integer[]> arr = new ArrayList<>();
int maxY = 0;
for (int i = 0; i < N; i++) {
int x = sc.nextInt();
int y = sc.nextInt();
if (y > maxY) {
maxY = y; // 가장 큰 높이 값
}
arr.add(new Integer[] { x, y });
}
Collections.sort(arr, new Comparator<Integer[]>() {
@Override
public int compare(Integer[] o1, Integer[] o2) {
// TODO Auto-generated method stub
return o1[0] - o2[0]; // x값을 기준으로 정렬
}
});
int sum = 0;
int x1 = arr.get(0)[0];
int y1 = arr.get(0)[1];
int i;
for (i = 0; i < arr.size(); i++) {
int y2 = arr.get(i)[1];
int x2 = arr.get(i)[0];
if (y1 < y2) { // 뒤 값이 더 크면 앞까지 넓이 업데이트
sum += (x2 - x1) * y1;
y1 = y2;
x1 = x2;
}
if (y2 == maxY) {
x1 = x2;
y1 = y2;
break;
}
} // 오름차순
// 가장 높은 값만큼 면적 업데이트
sum += y1; // y1=maxY
int x2 = 0;
int y2 = 0;
int x3 = arr.get(arr.size() - 1)[0]; // 마지막값
int y3 = arr.get(arr.size() - 1)[1];
// 내림차순 -> 뒤에서부터 검사
for (int j = arr.size() - 2; j > i; j--) {
y2 = arr.get(j)[1];
x2 = arr.get(j)[0];
if (y2 > y3) { // 가장 마지막 높이보다 크면 업데이트
sum += y3 * (x3 - x2);
x3 = x2;
y3 = y2;
}
}
sum += y3 * (x3 - x1); // 마지막 값 업데이트
System.out.println(sum);
}
}
'문제 풀이 > BOJ' 카테고리의 다른 글
[백준] 1874 - 스택수열 (자바/Java) (0) | 2022.08.18 |
---|---|
[백준] 2559 - 수열 (자바/Java) (0) | 2022.08.18 |
[백준] 1158 - 요세푸스 문제 (자바/Java) (0) | 2022.08.18 |
[백준] 4949 - 균형잡힌 세상 (자바/Java) 스택 Stack (0) | 2022.08.16 |
[백준] 9012 - 괄호 (자바/Java) 스택 Stack 괄호 검사 (0) | 2022.08.16 |