알고리즘/백준

[BOJ#6198] 옥상 정원 꾸미기

Jinoo.keem 2024. 4. 17. 23:57
728x90

https://www.acmicpc.net/problem/6198

 

6198번: 옥상 정원 꾸미기

문제 도시에는 N개의 빌딩이 있다. 빌딩 관리인들은 매우 성실 하기 때문에, 다른 빌딩의 옥상 정원을 벤치마킹 하고 싶어한다. i번째 빌딩의 키가 hi이고, 모든 빌딩은 일렬로 서 있고 오른쪽으

www.acmicpc.net

1 초 128 MB 18648 6909 5247 35.248%

문제

 

도시에는 N개의 빌딩이 있다.

빌딩 관리인들은 매우 성실 하기 때문에, 다른 빌딩의 옥상 정원을 벤치마킹 하고 싶어한다.

i번째 빌딩의 키가 hi이고, 모든 빌딩은 일렬로 서 있고 오른쪽으로만 볼 수 있다.

i번째 빌딩 관리인이 볼 수 있는 다른 빌딩의 옥상 정원은 i+1, i+2, .... , N이다.

그런데 자신이 위치한 빌딩보다 높거나 같은 빌딩이 있으면 그 다음에 있는 모든 빌딩의 옥상은 보지 못한다.

예) N=6, H = {10, 3, 7, 4, 12, 2}인 경우

             = 
 =           = 
 =     -     = 
 =     =     =        -> 관리인이 보는 방향
 =  -  =  =  =   
 =  =  =  =  =  = 
10  3  7  4  12 2     -> 빌딩의 높이
[1][2][3][4][5][6]    -> 빌딩의 번호
  • 1번 관리인은 2, 3, 4번 빌딩의 옥상을 확인할 수 있다.
  • 2번 관리인은 다른 빌딩의 옥상을 확인할 수 없다.
  • 3번 관리인은 4번 빌딩의 옥상을 확인할 수 있다.
  • 4번 관리인은 다른 빌딩의 옥상을 확인할 수 없다.
  • 5번 관리인은 6번 빌딩의 옥상을 확인할 수 있다.
  • 6번 관리인은 마지막이므로 다른 빌딩의 옥상을 확인할 수 없다.

따라서, 관리인들이 옥상정원을 확인할 수 있는 총 수는 3 + 0 + 1 + 0 + 1 + 0 = 5이다.

입력

  • 첫 번째 줄에 빌딩의 개수 N이 입력된다.(1 ≤ N ≤ 80,000)
  • 두 번째 줄 부터 N+1번째 줄까지 각 빌딩의 높이가 hi 입력된다. (1 ≤ hi ≤ 1,000,000,000)

출력

  • 각 관리인들이 벤치마킹이 가능한 빌딩의 수의 합을 출력한다.

제출 코드

import sys
N = int(input())
bd = []
for _ in range(N):
    bd.append(int(sys.stdin.readline()))
bd.reverse()
stack = []
stack.append(bd.pop())

sumone = 0
while bd:
    if not stack:
        stack.append(bd.pop())
    elif bd[-1] < stack[-1]:
        sumone += len(stack)
        stack.append(bd.pop())
    else:
        stack.pop()

print(sumone)

 

이해하는데 정말 오래걸린 문제. 로직을 이해하는데도 오래걸렸는데 구현도 도움을 조금 받았다..

이 문제의 핵심은 관리인이 옥상정원을 확인하는 총 수와 옥상정원에서 관리인을 보는 총 수가 같다는 것이다.

즉, 높은 빌딩에서 낮은 빌딩을 볼 때와, 낮은 빌딩에서 높은 빌딩을 확인하는 때가 같다.

새로운 스택을 만들고,

3번을 보는 10번(+1), 7번을 보는 10번(+1), 4번을 보는 7번과 10번(+2), 2번을 보는 12번(+1)을 구했다.

10번에서 3번보기(+1), 10번에서 7번보기(+1), 10번에서 7번 보기와 7번에서 4번보기(+2), 12번에서 2번보기(+1)는 위와 같다.

제출 코드(틀린 코드들)

# state 1
N = int(input())
bd = []
for _ in range(N):
    bd.append(int(input()))

sumone = 0 # 벤치마킹하는 빌딩총합
for i in range(N-1):
    for j in range(i+1, N):
        if bd[i] <= bd[j]:
            break
        if bd[i] > bd[j]:
            sumone += 1

print(sumone)

그리디하게 풀었던 첫번째 풀이, 냅다 완전탐색을 했더니 시간초과가 났다.

 

#state 2
from collections import deque

N = int(input())
bd = deque()
for _ in range(N):
    bd.append(int(input()))
    
st = []
sumone = 0
while bd:
    while True:
        if not st:
            if bd:
                st.append(bd.popleft())
            else:
                break
        elif bd[0] < st[-1]:
            st.append(bd.popleft())
            sumone += len(st) - 1
            break
        else:
            st.pop()
            break

print(sumone)

덱을 이용해서 직관적으로 이해하기 쉽게 짜보려했으나 IndexError가 났다.

 

'알고리즘 > 백준' 카테고리의 다른 글

[BOJ#3187] 양치기 꿍  (0) 2024.04.21
[BOJ#9625] BABBA  (0) 2024.04.18
[BOJ#10994] 별 찍기 - 19  (0) 2024.04.16
[BOJ#30892] 상어 키우기  (0) 2024.04.16
[BOJ#25418] 정수 a를 k로 만들기  (0) 2024.04.16