Lv2. [PCCP 기출문제] 2번 / 석유 시추

[PCCP 기출문제] 2번 / 석유 시추

프로그래머스 문제

문제 설명

세로길이가 n 가로길이가 m인 격자 모양의 땅 속에서 석유가 발견되었습니다. 석유는 여러 덩어리로 나누어 묻혀있습니다. 당신이 시추관을 수직으로 단 하나만 뚫을 수 있을 때, 가장 많은 석유를 뽑을 수 있는 시추관의 위치를 찾으려고 합니다. 시추관은 열 하나를 관통하는 형태여야 하며, 열과 열 사이에 시추관을 뚫을 수 없습니다.

예를 들어 가로가 8, 세로가 5인 격자 모양의 땅 속에 위 그림처럼 석유가 발견되었다고 가정하겠습니다. 상, 하, 좌, 우로 연결된 석유는 하나의 덩어리이며, 석유 덩어리의 크기는 덩어리에 포함된 칸의 수입니다. 그림에서 석유 덩어리의 크기는 왼쪽부터 8, 7, 2입니다.

시추관은 위 그림처럼 설치한 위치 아래로 끝까지 뻗어나갑니다. 만약 시추관이 석유 덩어리의 일부를 지나면 해당 덩어리에 속한 모든 석유를 뽑을 수 있습니다. 시추관이 뽑을 수 있는 석유량은 시추관이 지나는 석유 덩어리들의 크기를 모두 합한 값입니다. 시추관을 설치한 위치에 따라 뽑을 수 있는 석유량은 다음과 같습니다.

시각화

아래와 같이 석유 맵이 주어진다. 검은색이 석유가 매장 되어있는 것을 의미한다.

석유시추-1.png

매장량을 알기 위해 칸에 index 를 적어보자면 아래와 같다.

석유시추-2.png

석유 시추는 열 기준으로 한 칸 씩 움직이며 석유를 뽑는다. 이 때 석유를 뽑을 수 있는 최대량을 구해야 한다. 첫 번째 열부터 세 번쨰 열까지는 같은 석유 덩어리이다. 즉 어딜 파도 같은 양의 석유를 뽑을 수 있다.

석유시추-3.png

4 ~ 6 열은 다른 석유 덩어리를 파게 된다.

석유시추-4.png

7번 째 열의 경우 두 개의 덩어리를 파게 된다. 즉 7번 째 열을 시추할 경우 9개의 석유를 뽑을 수 있다.

8번 째는 한 개의 덩어리이고 2개의 석유를 뽑을 수 있다.

석유시추-5.png

문제 해결 과정

  1. 석유 덩어리 그룹화
    1. 각 덩어리에 좌표를 저장
  2. 각 덩어리에서 column 별로 석유량을 계산

지도를 돌며 석유 덩어리가 발견이 되면 bfs 로 석유 덩어리를 찾아낸다. bfs 를 돌며 반복되지 않도록 해당 좌표를 0으로 바꾸며 석유 덩어리를 찾아낸다.

column 별로 석유량을 계산하기 위해 dictionary 를 사용한다. 하나의 열이라도 해당이 되면 해당 석유 덩어리 전체를 시추할 수 있기 때문에 해당 열의 석유량을 더해준다.

전체 코드

from collections import deque, defaultdict

def solution(land):
    def bfs(start_y, start_x):
        queue = deque([(start_y, start_x)])
        coordinates = []

        while queue:
            y, x = queue.popleft()
            if y < 0 or y >= len(land) or x < 0 or x >= len(land[0]) or land[y][x] == 0:
                continue

            coordinates.append((y, x))
            land[y][x] = 0

            for dy, dx in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
                queue.append((y + dy, x + dx))

        return coordinates

    oil_maps = []
    for y in range(len(land)):
        for x in range(len(land[0])):
            if land[y][x] == 1:
                oil_maps.append(bfs(y, x))

    oil_amount_by_col = defaultdict(int)
    for oil_map in oil_maps:
        for col in set(coord[1] for coord in oil_map):
            oil_amount_by_col[col] += len(oil_map)

    return max(oil_amount_by_col.values())


print(solution([[0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0], [1, 1, 0, 0, 0, 1, 1, 0], [1, 1, 1, 0, 0, 0, 0, 0],
                [1, 1, 1, 0, 0, 0, 1, 1]]), 9)

print(solution([[1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 0], [1, 0, 0, 1, 0, 1],
                [1, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1]]
               ), 16)

석유시추-7.png


Lv1. 공원

[PCCE 기출문제] 10번 / 공원

Lv2. 타겟 넘버

깊이/너비 우선 탐색(DFS/BFS) > 타겟 넘버

NCloud LB & SourcePipeline 구축하기
tech collection 서비스 성능 개선하기
Selenium 복권 구매 자동화 만들어보기
디자인 패턴
책 리뷰
블로그 챌린지