문제 출처 : www.acmicpc.net/problem/6549
순서
I. 문제
II. 접근
III. 구현
I. 문제
히스토그램은 직사각형 여러 개가 아래쪽으로 정렬되어 있는 도형이다.
각 직사각형은 같은 너비를 가지고 있지만, 높이는 서로 다를 수도 있다.
예를 들어, 왼쪽 그림은 높이가 2, 1, 4, 5, 1, 3, 3이고 너비가 1인 직사각형으로 이루어진 히스토그램이다.
히스토그램에서 가장 넓이가 큰 직사각형을 구하는 프로그램을 작성하시오.
입력
입력은 테스트 케이스 여러 개로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 직사각형의 수 n이 가장 처음으로 주어진다. (1 ≤ n ≤ 100,000) 그 다음 n개의 정수 h1, ..., hn (0 ≤ hi ≤ 1,000,000,000)가 주어진다. 이 숫자들은 히스토그램에 있는 직사각형의 높이이며, 왼쪽부터 오른쪽까지 순서대로 주어진다. 모든 직사각형의 너비는 1이고, 입력의 마지막 줄에는 0이 하나 주어진다.
출력
각 테스트 케이스에 대해서, 히스토그램에서 가장 넓이가 큰 직사각형의 넓이를 출력한다.
[입력]
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
[출력]
8
4000
II. 접근
1. 왼쪽부터 오른쪽으로 탐색한다.( for문 )
2. 탐색할 때 다음 사각형의 높이가 stack.top()보다 크다면 현재idx와 h push().
3. 만약 작거나 같으면 stack.pop()하며 넓이 구한다.
4. 반복하다가 더 이상 stack.top()의 높이보다 작거나 같지 않으면 멈추고 push()
중요!!
여기서 push할 때 가장 마지막의 stack.top()의 idx와 현재 idx의 H를 넣어주어야 한다.
(그림참고)
그림설명
(1) (0,2) push
(2) 2 > 1 이므로 2 pop, 1 push
하지만 이때 idx = 0, h = 2로 push해준다!
(3) 1<3과 1<4이므로 2번 다 push
(4-1) 5>1 이므로 반복해서 pop
(4-2) stack.top() >= H[idx]이므로 모두 pop하고
바로 stack.idx와 현재idx의 H를 push하므로
(5) 나머지 2개 다 높기 때문에 모두 push()
(6) 스택에 남은 부분 처리
스택에 남은 부분 처리는 따로 처리할 필요 없이
마지막 블럭에 H = 0인 블럭을 추가하여 한 단계 더 진행하면 된다.
III. 구현
높이와, 경우의 수가 굉장히 크기 때문에 long long int 등의 큰 자료형을 사용해주어야 한다.
<hide/>
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;
typedef long long int lli;
// 구조체 정의
struct stu_stk {
lli order;
lli h;
};
stack<stu_stk> stk; //스택
vector<lli> ansV; //정답위한 Vector
int N;
lli H[100000+10];
lli maxA;
void input()
{
memset(H, 0, sizeof(H));
maxA = 0;
for (int j = 0; j < N; j++)
{
scanf("%lld", &H[j]);
}
}
lli solve()
{
lli refidx; // 가장 왼쪽 idx
for (int i = 0; i <= N; i++)
{
refidx = i;
// 같거나 작으면 처리해줌
while (!stk.empty() and stk.top().h >= H[i]) {
// 현재 stack에 있는 idx로 변경
refidx = stk.top().order;
// 넓이 구하고 업데이트
lli width = i - refidx;
lli tempA = width * stk.top().h;
if (maxA < tempA) maxA = tempA;
stk.pop();
}
// 여기서 refidx와 H[i]를 넣는것이 중요함.
// 이것으로 인해 좌측 우측 동시확인이 필요 없어짐.
// 어차피 높이는 H[i]일 것이고 순서를 앞쪽으로 당겨서
// 24242 같은 예외처리를 해주는 것
stk.push(stu_stk{ refidx, H[i] });
}
return maxA;
}
int main() {
while(1)
{
scanf("%d", &N);
if (N == 0) break;
else
{
input();
ansV.push_back(solve());
}
}
for(int i=0; i<lli(ansV.size());i++)
{
printf("%lld\n", ansV[i]);
}
return 0;
}
'Algorithm > Queue & Stack' 카테고리의 다른 글
[Algorithm][Stack][정올] 1328 : 빌딩 (0) | 2021.01.14 |
---|---|
[Algorithm][Queue] [백준] 1966 : 프린터 큐 (0) | 2021.01.09 |
[Algorithm][Stack] 스택 개념 및 구현 (0) | 2020.12.13 |
[Algorithm][Queue] Queue 개념 및 구현 (0) | 2020.12.07 |