https://www.acmicpc.net/problem/1725
1. 문제 설명
2. 풀이과정
해당 문제는 이전의 6549번 : 히스토그램에서 가장 큰 직사각형 문제와 유사한 문제이다.
하지만 이전 6549번 문제와 다른 점은 시간 제한이 1초에서 0.7초로 줄었다는 점이다.
시간 제한이 줄었기 때문에 6549번 문제를 풀었을 때처럼 해결하면 시간초과가 발생할 수 있다.
시간을 줄이기 위해 반복문이 최대한 적게 실행되도록 수정해보려고 했다.
하여 이전 6549번 코드의 for 문 안 while 반복문이 최소한으로 실행되도록 수정했다.
스택 자료구조를 그대로 사용하고 막대의 위치를 한 번씩만 가져와서 스택 자료구조에 막대가 있고 마지막으로 저장된 막대의 높이가 현재 지정하고 있는 막대의 높이보다 크면 막대를 제거하며 가장 큰 직사각형의 넓이를 구한다.
현재 지정하고 있는 막대의 위치와 직사각형의 넓이를 구할 때 지정하는 막대의 위치를 구별하기 위해 변수를 2개 사용하였다. (이 부분이 가장 이해하기 어려운 부분인 것 같다.)
현재 지정한 막대의 높이가 작으면 이전까지 저장되어 있던 막대를 하나씩 가져와 가져온 막대의 높이를 가지는 가장 큰 직사각형의 넓이를 구한다.
매번 직사각형의 넓이를 구하면 이전까지 저장되었던 가장 큰 직사각형 넓이와 비교하여 더 큰 값을 저장한다.
스택에 자료를 추가할 때는 위치와 막대의 높이를 리스트로 묶어 추가한다.
모든 막대를 가져와 직사각형의 넓이를 구한 뒤, 스택에 남아있는 막대들도 사용하여 가장 큰 직사각형 넓이를 구한 뒤 이전 값과 비교하여 큰 값을 저장한다.
이는 모든 막대가 동일한 높이로 주어졌을 경우를 고려한 것으로 전체 재탐색 후 가장 큰 직사각형 넓이를 구해야 한다.
- sys.stdin.readline() 함수를 사용하기 위해 sys 모듈을 불러온다. import sys
- 가로 칸의 수를 입력받는다. N = int(sys.stdin.readline())
- 각 막대의 높이를 저장할 리스트를 생성하고 hist = list()
- 가로 칸의 수만큼 높이를 입력받아 리스트에 추가한다. for _ in range(N): hist.append(int(sys.stdin.readline()))
- 스택 자료구조를 활용한다. stack = list()
- 최종 정답인 가장 큰 직사각형의 넓이를 저장할 변수를 생성하고 초기화한다. answer = 0
- 각 막대의 위치를 하나씩 불러오며 for i in range(N)
- 현재 막대의 위치를 따로 저장한다. idx = i
- 스택 자료구조가 비어있지 않거나 마지막으로 저장되어 있는 막대의 높이가 현재 막대의 높이보다 크다면 while (stack and stack[-1][1] > hist[i])
- 마지막으로 저장되어 있던 막대를 스택 자료구조에서 제거하고 막대의 위치와 높이를 가져온다. idx, height = stack.pop()
- 현재 막대의 위치에서 가져온 막대의 위치를 뺀 값(밑변 길이)에 가져온 막대의 높이를 곱하여 값을 저장한다. rst = (i - idx) * height
- 새롭게 구한 직사각형의 넓이와 기존에 저장되어 있던 직사각형의 넓이 중 더 큰 값을 정답 변수에 저장한다. answer = max(answer, rst)
- 막대의 위치와 현재 막대의 높이를 리스트로 묶어 스택 자료구조에 추가한다. stack.append([idx, hist[i]])
- 모든 막대를 가져와 가장 큰 직사각형의 넓이를 구했다면 이후 스택 자료구조에 저장되어 있는 막대들도 살펴봐야 한다. 스택 자료구조가 비기 전까지 반복하며 while (stack)
- 마지막으로 저장되어 있던 막대를 스택 자료구조에서 제거하고 막대의 위치와 높이를 가져와 idx, height = stack.pop()
- 마지막 막대의 위치에서부터 가져온 막대의 위치를 빼고(밑변 길이) 그 값에 가져온 막대의 높이를 곱해 rst = (N - idx) * height
- 새롭게 구한 직사각형의 넓이와 기존에 저장되어 있던 직사각형의 넓이 중 더 큰 값을 정답 변수에 저장한다. answer = max(answer, rst)
- 최종적으로 구한 가장 큰 직사각형의 넓이를 출력한다. print(answer)
3. 소스코드
import sys
N = int(sys.stdin.readline())
hist = list()
for _ in range(N):
hist.append(int(sys.stdin.readline()))
stack = list()
answer = 0
for i in range(N):
idx = i
while (stack and stack[-1][1] > hist[i]):
idx, height = stack.pop()
rst = (i - idx) * height
answer = max(answer, rst)
stack.append([idx, hist[i]])
while (stack):
idx, height = stack.pop()
rst = (N - idx) * height
answer = max(answer, rst)
print(answer)
'백준' 카테고리의 다른 글
[백준] 7576번 : 토마토 - 파이썬(Python) - 우당탕탕 개발자 되기 프로젝트 (0) | 2024.10.06 |
---|---|
[백준] 17299번 : 오등큰수 - 파이썬(Python) - 우당탕탕 개발자 되기 프로젝트 (0) | 2024.09.11 |
[백준] 9935번 : 문자열 폭발 - 파이썬(Python) - 우당탕탕 개발자 되기 프로젝트 (0) | 2024.09.09 |
[백준] 7579번 : 앱 - 파이썬(Python) - 우당탕탕 개발자 되기 프로젝트 (0) | 2024.09.08 |
[백준] 2293번 : 동전 1 - 파이썬(Python) - 우당탕탕 개발자 되기 프로젝트 (0) | 2024.09.07 |
[백준] 2629번 : 양팔저울 - 파이썬(Python) - 우당탕탕 개발자 되기 프로젝트 (0) | 2024.08.28 |
[백준] 1520번 : 내리막 길 - 파이썬(Python) - 우당탕탕 개발자 되기 프로젝트 (0) | 2024.08.03 |
[백준] 11049번 : 행렬 곱셈 순서 - 파이썬(Python) - 우당탕탕 개발자 되기 프로젝트 (0) | 2024.07.31 |