본문 바로가기
Algorithm/Baekjoon

2616. 소형기관차 (Python)

by 원만사 2022. 3. 13.
반응형
 

2616번: 소형기관차

첫째 줄에 기관차가 끌고 가던 객차의 수가 입력된다. 그 수는 50,000 이하이다. 둘째 줄에는 기관차가 끌고 가던 객차에 타고 있는 손님의 수가 1번 객차부터 차례로 입력된다. 한 객차에 타고 있

www.acmicpc.net

 

풀이

 구간합 개념과 dp를 사용하여 해결할 수 있다. dp 배열은 2차원 배열로 이루어져 있는데 의미는 다음과 같다.

    # dp[1][n]: n번째 객차까지 1개의 소형 기관차를 사용했을 때 운송할 수 있는 최대 손님 수
    # dp[2][n]: n번째 객차까지 2개의 소형 기관차를 사용했을 때 운송할 수 있는 최대 손님 수
    # dp[3][n]: n번째 객차까지 3개의 소형 기관차를 사용했을 때 운송할 수 있는 최대 손님 수
    dp = [[0 for _ in range(N+1)] for _ in range(4)]

 

 소형 기관차가 최대로 끌 수 있는 객차의 수를 M이라 하고 먼저 처음 M개의 객차까지의 손님에 대하여 합을 구한다. 이 구간합은 처음 M개의 객차까지 1개의 소형 기관차를 사용했을 때의 최댓값을 의미하므로 dp[1][M]에 구간합을 먼저 대입한다. 그 후 bottom-up 방식으로 dp 배열을 채워나간다.

 

 M+1 이후의 객차(i 번째)를 살펴보면서 해당 범위에 맞춰 구간합을 갱신한다. 그 후 dp[1][i]는 이전 i-1번째 까지의 소형 기관차 1개를 사용했을 때의 최댓값과 현재 구간합을 비교하여 갱신해나간다. 이를 통해 dp[1][i]의 경우는 i번째까지 1개의 소형 기관차를 사용했을 때 태울 수 있는 손님의 최댓값이 담기게 된다.

dp[1][i] = max(dp[1][i-1], sums) # i번째 객차까지 1개의 소형 기관차를 사용했을 때 최댓값 갱신

 

 2개(또는 3개)의 소형 기관차를 사용하는 경우는 i-1번째 객차까지 2개(또는 3개)의 소형 기관차를 사용했을 때의 태울 수 있는 손님의 최댓값과 i-M번째 객차까지 1개(또는 2개)의 소형 기관차를 사용했을 때 태울 수 있는 손님의 최댓값에 현재 구간합을 합한 값을 비교하여 큰 값을 dp[2][i](또는 dp[3][i])에 갱신해나간다. 이를 통해 dp[2][i](또는 dp[3][i])에는 i번째까지 2개(또는 3개)의 소형 기관차를 사용했을 때 태울 수 있는 손님의 최댓값이 담기게 된다.

 

 마지막에 dp[3][N]을 출력하여 답을 구할 수 있다.

 

코드

import sys
input = sys.stdin.readline

if __name__ == '__main__':
    N = int(input())  # 기관차가 끌고 가던 객차의 수
    people = [0] + list(map(int, input().split()))
    M = int(input())  # 소형 기관차가 최대로 끌 수 있는 객차의 수

    # dp[1][n]: n번째 객차까지 1개의 소형 기관차를 사용했을 때 운송할 수 있는 최대 손님 수
    # dp[2][n]: n번째 객차까지 2개의 소형 기관차를 사용했을 때 운송할 수 있는 최대 손님 수
    # dp[3][n]: n번째 객차까지 3개의 소형 기관차를 사용했을 때 운송할 수 있는 최대 손님 수
    dp = [[0 for _ in range(N+1)] for _ in range(4)] 
    sums = 0 # 구간합

    # 최초 M개의 객차까지의 구간합을 구해놓는다.
    for i in range(1, M+1): 
        sums += people[i]
    dp[1][M] = sums # M번째 객차까지는 1개의 소형 기관차만 사용할 수 있다. 

    # 이제 M번째 이후의 객차부터 차례대로 살펴본다.
    for i in range(M+1, N+1):
        sums = sums - people[i-M] + people[i] # 구간합 갱신 
        dp[1][i] = max(dp[1][i-1], sums) # i번째 객차까지 1개의 소형 기관차를 사용했을 때 최댓값 갱신

        if i >= M*2: # 2개의 소형 기관차를 채울 수 있다면
            # i-1번째 객차까지 2개의 소형 기관차를 사용했을 때의 손님 수와
            # 현재 구간합에 i-M번째 객차까지 1개의 소형 기관차를 사용했을 때의 최대 손님수를 합한 수를 
            # 비교하여 큰 값으로 갱신
            dp[2][i] = max(dp[2][i-1], sums + dp[1][i-M]) 

        if i >= M*3: # 3개의 소형 기관차를 채울 수 있다면
            # i-1번째 객차까지 3개의 소형 기관차를 사용했을 때의 손님 수와
            # 현재 구간합에 i-M번째 객차까지 2개의 소형 기관차를 사용했을 때의 최대 손님수를 합한 수를 
            # 비교하여 큰 값으로 갱신
            dp[3][i] = max(dp[3][i-1], sums + dp[2][i-M])

    print(dp[3][N])
반응형

'Algorithm > Baekjoon' 카테고리의 다른 글

15997. 승부 예측 (Python)  (0) 2022.03.15
1405. 미친 로봇 (Python)  (0) 2022.03.15
1655. 가운데를 말해요 (Python)  (0) 2022.03.12
3078. 좋은 친구 (Python)  (0) 2022.03.10
9663. N-Queen (Python)  (0) 2022.03.08

댓글