본문 바로가기
백준알고리즘/스택

(Python/플5)백준알고리즘 6549번: 히스토그램에서 가장 큰 직사각형

by windy7271 2023. 7. 17.
728x90
반응형

 

 

문제:

히스토그램은 직사각형 여러 개가 아래쪽으로 정렬되어 있는 도형이다. 각 직사각형은 같은 너비를 가지고 있지만, 높이는 서로 다를 수도 있다. 예를 들어, 왼쪽 그림은 높이가 2, 1, 4, 5, 1, 3, 3이고 너비가 1인 직사각형으로 이루어진 히스토그램이다.

히스토그램에서 가장 넓이가 큰 직사각형을 구하는 프로그램을 작성하시오.

입력:

 

입력은 테스트 케이스 여러 개로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 직사각형의 수 n이 가장 처음으로 주어진다. (1 ≤ n ≤ 100,000) 그 다음 n개의 정수 h1, ..., hn (0 ≤ hi ≤ 1,000,000,000)가 주어진다. 이 숫자들은 히스토그램에 있는 직사각형의 높이이며, 왼쪽부터 오른쪽까지 순서대로 주어진다. 모든 직사각형의 너비는 1이고, 입력의 마지막 줄에는 0이 하나 주어진다.

출력:

 

각 테스트 케이스에 대해서, 히스토그램에서 가장 넓이가 큰 직사각형의 넓이를 출력한다.

 

풀이:

import sys
sys.stdin = open('/Users/song/Desktop/Python/Python/h.txt', 'r')

while True:
    n, *heights = map(int, input().split())
    if n == 0:
        break

    stack = []  # 높이를 저장할 스택
    max_area = 0  # 가장 큰 직사각형의 넓이
    for i in range(n):
        while stack and heights[i] < heights[stack[-1]]: # 스택이 있고, 다음 건물 높이가 스택 마지막 보다 낮을때까지
            height = heights[stack.pop()] # 높이는 스택 마지막 건물 높
            width = i if not stack else i - stack[-1] - 1 # i번째 까지의 최소 높이
            area = height * width # 면적
            max_area = max(max_area, area) # 최대 면적 구해준다.
        stack.append(i) # 스택이 비어있으면
    while stack: # 스택이 남아있으며 예제2번같이 똑같이 해준다.
        height = heights[stack.pop()]
        width = n if not stack else n - stack[-1] - 1
        area = height * width
        max_area = max(max_area, area)

    print(max_area)

 

플래문제가 궁금해서 많이 제출하고 정답률 높은 문제를 한 번 풀어보았다.

 

이 문제는 스택을 사용해주어야한다.

최댓값을 가져오려면 다음 들어올 건물이 스택에 있는 건물보다 높아야하고 그렇지 않은경우에 넓이를 최신화 시켜주면된다.

 

만약 예제처럼 

높이가 2, 1, 4, 5, 1, 3, 3 이렇게 오면

 

스택에 2가 들어가있고 1이 들어오면 높이가 낮아지므로 최댓값을 최신화 시켜준다.

그러면 높이는 stk에서 뽑은 값 이다.

 

stack이 비어있지 않을 경우, 즉 이전에 처리한 직사각형이 있을 경우에는 현재 직사각형의 인덱스 i와 스택의 상단에 있는 직사각형의 인덱스 stack[-1] 사이의 거리를 구한다.

  • stack[-1]은 스택의 가장 위에 있는 직사각형의 인덱스를 의미한다.
  • i - stack[-1] - 1을 계산하면, 현재 직사각형과 스택의 상단 직사각형 사이에 있는 직사각형의 개수가 된다. .

i = 4일때 예를들어 보면

스택에섯 [1,4,5] 가 들어오고 1과 만나면 서 5와 4 를 팝한다.

그럼

5를 pop할때 (4-2-1) * 5

4를 pop할때 (4-1-1) * 4 

앞에께 witdh 가 되고 뒤에가 높이가 된다. 

 

다 하고나면 스택에는 [1,4,5,6] 이 남게 된다.

그럼 남은 부분에서도 넓이를 처리해 주어야한다.

 

근데 여기서는 width 대신 

width = n if not stack else n - stack[-1] - 1

n으로 바꿔줘야한다.

 

간단하게 말하면 6일때는 h 3이고 w = 1이다

5일때는 h 3 w 2 

4일때는 h 1 w 3

1 일때는 h 1 w 7 

이렇게 되는것이다.

 

그거를 식으로 나타태면

height = heights[stack.pop()]
width = n if not stack else n - stack[-1] - 1
area = height * width

이렇게 된다.

 

 

반응형

댓글