https://www.acmicpc.net/problem/2304
문제
N 개의 막대 기둥이 일렬로 세워져 있다. 기둥들의 폭은 모두 1 m이며 높이는 다를 수 있다. 이 기둥들을 이용하여 양철로 된 창고를 제작하려고 한다. 창고에는 모든 기둥이 들어간다. 이 창고의 지붕을 다음과 같이 만든다.
- 지붕은 수평 부분과 수직 부분으로 구성되며, 모두 연결되어야 한다.
- 지붕의 수평 부분은 반드시 어떤 기둥의 윗면과 닿아야 한다.
- 지붕의 수직 부분은 반드시 어떤 기둥의 옆면과 닿아야 한다.
- 지붕의 가장자리는 땅에 닿아야 한다.
- 비가 올 때 물이 고이지 않도록 지붕의 어떤 부분도 오목하게 들어간 부분이 없어야 한다.
그림 1은 창고를 옆에서 본 모습을 그린 것이다. 이 그림에서 굵은 선으로 표시된 부분이 지붕에 해당되고, 지붕과 땅으로 둘러싸인 다각형이 창고를 옆에서 본 모습이다. 이 다각형을 창고 다각형이라고 하자.
창고 주인은 창고 다각형의 면적이 가장 작은 창고를 만들기를 원한다. 그림 1에서 창고 다각형의 면적은 98 ㎡이고, 이 경우가 가장 작은 창고 다각형이다.
기둥들의 위치와 높이가 주어질 때, 가장 작은 창고 다각형의 면적을 구하는 프로그램을 작성하시오.
입력
첫 줄에는 기둥의 개수를 나타내는 정수 N이 주어진다. N은 1 이상 1,000 이하이다. 그 다음 N 개의 줄에는 각 줄에 각 기둥의 왼쪽 면의 위치를 나타내는 정수 L과 높이를 나타내는 정수 H가 한 개의 빈 칸을 사이에 두고 주어진다. L과 H는 둘 다 1 이상 1,000 이하이다.
출력
첫 줄에 창고 다각형의 면적을 나타내는 정수를 출력한다.
🔵풀이
일반적인 구현 문제란 생각을 했습니다. 먼저 가장 높은 기둥을 기준으로 왼쪽, 오른쪽 모두 계속해서 감소하는 형태를 만들어야 합니다. 그렇지 않으면 아래와 같이 물 웅덩이가 만들어지기 때문입니다. 그래서 x좌표를 기준으로 정렬후에 가장 높은 기둥을 기준으로 잡아 시작부터 max 기둥까지는 계속해서 증가하게끔, max 기둥부터 끝까지는 계속해서 감소하게끔 코드를 작성했습니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Stack;
import java.util.StringTokenizer;
class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.valueOf(br.readLine());
StringTokenizer stringTokenizer;
ArrayList<int[]> arrayList = new ArrayList<>();
int max = Integer.MIN_VALUE;
int answer = 0;
int[] tmp = new int[2];
Stack<int[]> stack = new Stack<>();
int index = 0;
for (int i=0; i<N; i++){
stringTokenizer = new StringTokenizer(br.readLine());
int x = Integer.valueOf(stringTokenizer.nextToken());
int y = Integer.valueOf(stringTokenizer.nextToken());
arrayList.add(new int[]{x,y});
if (max<=y){
if (max==y&&tmp[0]<arrayList.get(i)[0]){
max = y;
tmp = arrayList.get(i);
continue;
} else if (max==y&&tmp[0]>arrayList.get(i)[0]) {
continue;
}
max = y;
tmp = arrayList.get(i);
}
}
Collections.sort(arrayList, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0]-o2[0];
}
});
index = arrayList.indexOf(tmp);
stack.add(arrayList.get(0));
for (int i=1; i<=index; i++){
if (stack.peek()[1]<=arrayList.get(i)[1]){
answer+=(arrayList.get(i)[0]-stack.peek()[0])*stack.peek()[1];
stack.add(arrayList.get(i));
}
}
stack.clear();
answer+=arrayList.get(index)[1];
if (index!=N-1) {
stack.add(arrayList.get(index + 1));
}
else{
System.out.println(answer);
return;
}
for (int i=index+2; i<N; i++){
if (stack.peek()[1]<arrayList.get(i)[1]){
while (!stack.isEmpty()&&stack.peek()[1]<arrayList.get(i)[1]){
stack.pop();
}
}
stack.add(arrayList.get(i));
}
int beforeX;
int beforeY;
int afterX;
while (stack.size()>1){
beforeX = stack.peek()[0];
beforeY = stack.peek()[1];
stack.pop();
afterX = stack.peek()[0];
answer += (beforeX-afterX)*beforeY;
}
beforeX = stack.peek()[0];
beforeY = stack.peek()[1];
answer += (beforeX-arrayList.get(index)[0])*beforeY;
System.out.println(answer);
}
}
'알고리즘' 카테고리의 다른 글
백준 1260번 : DFS와 BFS (0) | 2024.08.03 |
---|---|
백준 1138번 : 한 줄로 서기(자바) (0) | 2024.08.02 |
백준 11501번 : 주식(자바) (0) | 2024.08.01 |
백준 19637번 : IF문 좀 대신 써줘(자바) (0) | 2024.07.30 |
백준 2607번 : 비슷한 단어(자바) (1) | 2024.07.26 |