문제 주소 : www.acmicpc.net/problem/6549
6549번: 히스토그램에서 가장 큰 직사각형
입력은 테스트 케이스 여러 개로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 직사각형의 수 n이 가장 처음으로 주어진다. (1 ≤ n ≤ 100,000) 그 다음 n개의 정수 h1, ..., hn (0 ≤ hi ≤
www.acmicpc.net
문제 확인
특별한 알고리즘이 필요 없는 스택을 이용한 구현 문제입니다.
풀이
입력받은 직사각형의 높이와 i 값을 스택에 쌓으면서 기록합니다. 다음 나오는 직사각형의 높이에 따라 다음과 같이 동작합니다.
- 다음 직사각형의 높이에 높다면 계속해서 스택을 쌓아갑니다.
- 높이가 같은 경우 시작 지점인 i값을 기록해 두었으므로 스택에 넣을 필요가 없습니다.
- 다음 직사각형의 높이가 낮다면 스텍에서 만들 수 있는 직사각형만큼 체크를 합니다.
만들 수 있는 직사각형의 가로길이는 i - idx[top] 이며 높이는 stack[top]입니다. 스택에 기록된 직사각형 들은 오름차순으로 정렬되어 있는 상태이므로 스택 아래에 저장되어 있는 직사각형의 가로길이는 사이에 포함된 직사각형들을 포함할 수 있기 때문에 현재 지점인 i, 높이에 해당하는 막대의 위치 idx[top]과의 차이가 됩니다. 이러한 과정을 stack[top] > h일 때까지 반복합니다.
i=3에서 i=4가 되는 경우 2, 3에 해당하는 히스토그램에서 만들 수 있는 직사각형을 체크하고 스택에서 빼냅니다. 이때 i=4에 해당하는 막대의 h값만 기록해도 되는 이유는 시작 위치가 이미 이전에 기록된 상태이기 때문에 바꿀 필요가 없습니다.
모든 탐색이 끝나고 나면 직사각형의 가로 길이는 n - idx[top]이 되며 스택에 남은 막대들을 같은 방식으로 계산합니다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include <iostream>
using namespace std;
int main() {
cin.tie(NULL);
ios::sync_with_stdio(false);
int stack[100001] = { -1 }, idx[100001], top = 0;
int n;
cin >> n;
while (n) {
long long max = 0, size;
for (int i = 0, t; i < n; i++) {
cin >> t;
if (stack[top] > t) {//다음 직사각형이 작은 경우
do {
size = ((long long)i - idx[top]) * stack[top];
max = max < size ? size : max;
--top;
} while (stack[top] > t);//만들 수 있는 직사각형 체크
if (t)
stack[++top] = t;//i값은 남아있는 흔적을 이용하고, h값만 기록
}
else if (t && stack[top] < t) {//직사각형이 큰 경우
stack[++top] = t;
idx[top] = i;//스텍에 추가
}
}
while (top != 0) {//남은 히스토그램 처리
size = ((long long)n - idx[top]) * stack[top];
max = max < size ? size : max;
--top;
}
cout << max << '\n';
cin >> n;
}
}
|
cs |
'알고리즘 문제 > [백준]' 카테고리의 다른 글
[백준] 2534 카드 배열 (0) | 2021.01.25 |
---|---|
[백준] 2252 줄 세우기 (0) | 2021.01.24 |
[백준] 16287 Parcel (0) | 2021.01.21 |
[백준] 1256 사전 (0) | 2021.01.20 |
[백준] 7579 앱 (0) | 2021.01.18 |