알고리즘 연습/브루트 포스

[🥈2 / 백준 2304 / 파이썬] 창고 다각형

김세진 2021. 9. 28. 01:48
반응형

 

 

2304번: 창고 다각형

첫 줄에는 기둥의 개수를 나타내는 정수 N이 주어진다. N은 1 이상 1,000 이하이다. 그 다음 N 개의 줄에는 각 줄에 각 기둥의 왼쪽 면의 위치를 나타내는 정수 L과 높이를 나타내는 정수 H가 한 개의

www.acmicpc.net

 

문제

N 개의 막대 기둥이 일렬로 세워져 있다. 기둥들의 폭은 모두 1 m이며 높이는 다를 수 있다. 이 기둥들을 이용하여 양철로 된 창고를 제작하려고 한다. 창고에는 모든 기둥이 들어간다. 이 창고의 지붕을 다음과 같이 만든다.

  1. 지붕은 수평 부분과 수직 부분으로 구성되며, 모두 연결되어야 한다.
  2. 지붕의 수평 부분은 반드시 어떤 기둥의 윗면과 닿아야 한다.
  3. 지붕의 수직 부분은 반드시 어떤 기둥의 옆면과 닿아야 한다.
  4. 지붕의 가장자리는 땅에 닿아야 한다.
  5. 비가 올 때 물이 고이지 않도록 지붕의 어떤 부분도 오목하게 들어간 부분이 없어야 한다.

그림 1은 창고를 옆에서 본 모습을 그린 것이다. 이 그림에서 굵은 선으로 표시된 부분이 지붕에 해당되고, 지붕과 땅으로 둘러싸인 다각형이 창고를 옆에서 본 모습이다. 이 다각형을 창고 다각형이라고 하자.

그림1 . 기둥과 지붕(굵은 선)의 예

창고 주인은 창고 다각형의 면적이 가장 작은 창고를 만들기를 원한다. 그림 1에서 창고 다각형의 면적은 98 ㎡이고, 이 경우가 가장 작은 창고 다각형이다.

기둥들의 위치와 높이가 주어질 때, 가장 작은 창고 다각형의 면적을 구하는 프로그램을 작성하시오.

입력

첫 줄에는 기둥의 개수를 나타내는 정수 N이 주어진다. N은 1 이상 1,000 이하이다. 그 다음 N 개의 줄에는 각 줄에 각 기둥의 왼쪽 면의 위치를 나타내는 정수 L과 높이를 나타내는 정수 H가 한 개의 빈 칸을 사이에 두고 주어진다. L과 H는 둘 다 1 이상 1,000 이하이다.

출력

첫 줄에 창고 다각형의 면적을 나타내는 정수를 출력한다.

 

예제 입력 

7
2 4
11 4
15 8
4 6
5 3
8 10
13 6

예제 출력 

98






 

풀이

 

풀고나서 검색해보니 훨씬 쉽게 푸는 방법이 있지만,

일단 필자는 브루트 포스로 해결했으니 브루트 포스로 포스팅하겠다.

 

입력받은 막대를 인덱스 순서로 정렬하고 왼쪽부터 차례로 훑는다.

훑을 때마다 해당 인덱스부터 시작하여 끝까지 훑되, 중간에 현재 막대보다 큰 것이 나온다면 멈추고 넓이를 구해준다.

끝까지 순회했는데 현재 막대보다 큰 것이 나오지 않는다면 현재 막대의 크기를 더하고, 가장 컸던 막대를 기준으로 나머지 넓이를 구해준다.

 

import sys
input = sys.stdin.readline

n = int(input())
board = sorted([tuple(map(int,input().split())) for _ in range(n)])

last_idx, last_h = board[0]
result = 0
while(True):
    max_idx,max_h = 0,0
    # 현재 위치부터 큰 것이 나올 때까지 탐색
    for j in range(board.index((last_idx,last_h))+1,n):
        cur_idx,cur_h = board[j]
        if cur_h > last_h:
            result += (cur_idx-last_idx)*last_h
            last_idx,last_h = cur_idx,cur_h
            break
        if cur_h > max_h:
            max_idx,max_h = cur_idx,cur_h
    # 현재 위치보다 큰 것이 없다면 가장 컸던 것까지만 곱해주고 인덱스를 그곳으로 옮김
    else:
        result += last_h + (max_idx-last_idx-1)*max_h
        last_idx,last_h = max_idx,max_h
        if last_idx == 0:
            break
print(result)

 

해당 방법보다 가장 큰 막대를 기준으로 왼쪽, 오른쪽으로 나눈 뒤 큰 막대 방향으로 순회하며 넓이를 구하는 방법이 훨씬 쉽다.

 

반응형