[ 카카오 / Python ] 2023 KAKAO BLIND RECRUITMENT - 택배 배달과 수거하기

박제현·2024년 3월 17일
0

코딩테스트

목록 보기
79/101

문제 설명

당신은 일렬로 나열된 n개의 집에 택배를 배달하려 합니다. 배달할 물건은 모두 크기가 같은 재활용 택배 상자에 담아 배달하며, 배달을 다니면서 빈 재활용 택배 상자들을 수거하려 합니다.
배달할 택배들은 모두 재활용 택배 상자에 담겨서 물류창고에 보관되어 있고, i번째 집은 물류창고에서 거리 i만큼 떨어져 있습니다. 또한 i번째 집은 j번째 집과 거리 j - i만큼 떨어져 있습니다. (1 ≤ i ≤ j ≤ n)
트럭에는 재활용 택배 상자를 최대 cap개 실을 수 있습니다. 트럭은 배달할 재활용 택배 상자들을 실어 물류창고에서 출발해 각 집에 배달하면서, 빈 재활용 택배 상자들을 수거해 물류창고에 내립니다. 각 집마다 배달할 재활용 택배 상자의 개수와 수거할 빈 재활용 택배 상자의 개수를 알고 있을 때, 트럭 하나로 모든 배달과 수거를 마치고 물류창고까지 돌아올 수 있는 최소 이동 거리를 구하려 합니다. 각 집에 배달 및 수거할 때, 원하는 개수만큼 택배를 배달 및 수거할 수 있습니다.

다음은 cap=4 일 때, 최소 거리로 이동하면서 5개의 집에 배달 및 수거하는 과정을 나타낸 예시입니다.

배달 및 수거할 재활용 택배 상자 개수

집 #1집 #2집 #3집 #4집 #5
배달1개0개3개1개2개
수거0개3개0개4개0개

배달 및 수거 과정

집 #1집 #2집 #3집 #4집 #5설명
남은 배달/수거1/00/33/01/42/0물류창고에서 택배 3개를 트럭에 실어 출발합니다.
남은 배달/수거1/00/33/00/40/0물류창고에서 5번째 집까지 이동하면서(거리 5) 4번째 집에 택배 1개를 배달하고, 5번째 집에 택배 2개를 배달합니다.
남은 배달/수거1/00/33/00/00/05번째 집에서 물류창고까지 이동하면서(거리 5) 4번째 집에서 빈 택배 상자 4개를 수거한 후, 수거한 빈 택배 상자를 물류창고에 내리고 택배 4개를 트럭에 싣습니다.
남은 배달/수거0/00/30/00/00/0물류창고에서 3번째 집까지 이동하면서(거리 3) 1번째 집에 택배 1개를 배달하고, 3번째 집에 택배 3개를 배달합니다.
남은 배달/수거0/00/00/00/00/03번째 집에서 물류창고까지 이동하면서(거리 3) 2번째 집에서 빈 택배 상자 3개를 수거한 후, 수거한 빈 택배 상자를 물류창고에 내립니다.

16(=5+5+3+3)의 거리를 이동하면서 모든 배달 및 수거를 마쳤습니다. 같은 거리로 모든 배달 및 수거를 마치는 다른 방법이 있지만, 이보다 짧은 거리로 모든 배달 및 수거를 마치는 방법은 없습니다.

트럭에 실을 수 있는 재활용 택배 상자의 최대 개수를 나타내는 정수 cap, 배달할 집의 개수를 나타내는 정수 n, 각 집에 배달할 재활용 택배 상자의 개수를 담은 1차원 정수 배열 deliveries와 각 집에서 수거할 빈 재활용 택배 상자의 개수를 담은 1차원 정수 배열 pickups가 매개변수로 주어집니다. 이때, 트럭 하나로 모든 배달과 수거를 마치고 물류창고까지 돌아올 수 있는 최소 이동 거리를 return 하도록 solution 함수를 완성해 주세요.

제한 사항

  • 1 ≤ cap ≤ 50
  • 1 ≤ n ≤ 100,000
  • deliveries의 길이 = pickups의 길이 = n
    • deliveries[i]는 i+1번째 집에 배달할 재활용 택배 상자의 개수를 나타냅니다.
    • pickups[i]는 i+1번째 집에서 수거할 빈 재활용 택배 상자의 개수를 나타냅니다.
    • 0 ≤ deliveries의 원소 ≤ 50
    • 0 ≤ pickups의 원소 ≤ 50
  • 트럭의 초기 위치는 물류창고입니다.

입출력 예

capndeliveriespickupsresult
45[1, 0, 3, 1, 2][0, 3, 0, 4, 0]16
27[1, 0, 2, 0, 1, 0, 2][0, 2, 0, 1, 0, 2, 0]30

풀이

처음 봤을 때, 딱 전형적인 그리디 문제이겠다. 생각이 들었다.
실제로도 그리디 문제가 맞았고 정답 풀이도 그리디 알고리즘이 맞다.

근데, 나의 문제는 그리디라고 생각을 했음에도, 그에 해당하는 코드를 작성하지 못했다.

가장 멀리 있는 택배 부터 배송하고 돌아오면서 수거를 하면 되는 간단한 문제인데..

이 두가지를 코드로 구현할 수 가 없었다.

가장 멀리 있는 집부터 택배를 배송하는데, 거기서 돌아오면서 택배를 수거하니..

가능한 택배를 많이 싣고 가서 배송을 먼저 다 하고, 가장 먼 집에서 다시 돌아오면서 가능한 많이 수거를 해오면 되는 게 전부이다.

대신 이동거리는 가장 먼 집의 거리 2배가 된다.

유튜브 해설을 참조하여 풀이했다.

코드

from collections import deque
def solution(cap, n, deliveries, pickups):
    answer = 0

    idps = [(i, d, p) for i, (d, p) in enumerate(zip(deliveries, pickups), 1) if d or p]


    delivery = 0
    pickup = 0
    while idps:
        i, d, p = idps.pop()
        delivery += d
        pickup += p
        while delivery > 0 or pickup > 0:
            delivery -= cap
            pickup -= cap
            answer += i*2
    print(answer)
    return answer

profile
닷넷 새싹

0개의 댓글