Problem


앞으로 남은 근무일과 상담일정이 주어졌을 때 상담으로 얻는 최대 수익을 구하는 문제입니다.



Solution

DP 문제입니다.


for 문을 뒤에서부터 시작하여 dp 값을 차곡차곡 쌓아서 dp[1] 을 출력해주면 됩니다.


example


1일에는 3일동안 상담을 할 수 있으므로 1, 2, 3 일을 소모하게 됩니다.


그럼 최대한 많은 금액을 받기 위해서는


1일 금액 + 4일부터 받을 수 있는 최대 금액


이것이 1일에 상담을 할 경우 얻을 수 있는 최대 금액입니다.


x일부터 받을 수 있는 최대 금액을 저장하기 위해 dp 배열을 사용합니다.


P[1] + dp[4] 라는 첫번째 식을 얻었습니다.


그런데 1일에 상담을 하는 경우보다 2일에 상담을 하는 경우가 최고 금액일 수 있습니다.


예를 들어 P[1] + dp[4] 의 금액이 50인데 dp[2] 가 100 일 가능성이 있습니다.


그러므로 두 개의 값 중 더 큰 값이 1일부터 받을 수 있는 최대 금액입니다.


dp[1] = MAX(P[1] + dp[4], dp[2])


일반 수식으로 변환하면


dp[i] = MAX(P[i] + dp[i+T[i]], dp[i+1])


만약 상담일이 퇴사일을 초과하면 자동으로 dp[i+1] 의 값이 받을수 있는 최대금액이 됩니다.


마지막 날에도 1일의 상담을 할 수 있습니다. i + T[i] <= N + 1 로 수식을 세워야 합니다.


대신 배열을 선언할 때 1 의 여유공간을 추가로 더 선언합니다.



Java Code

import java.util.*;
import java.io.*;
import java.lang.*;

class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        int N = Integer.parseInt(br.readLine());
        int[] T = new int[N + 2];
        int[] P = new int[N + 2];
        int[] dp = new int[N + 2];

        for (int i = 1; i <= N; i++) {
            st = new StringTokenizer(br.readLine());
            T[i] = Integer.parseInt(st.nextToken());
            P[i] = Integer.parseInt(st.nextToken());
        }

        for (int i = N; i > 0; i--) {
            int day = i + T[i];     // i번째 날의 상담기간

            if (day <= N + 1)
                dp[i] = Math.max(P[i] + dp[day], dp[i + 1]);
            else    // 상담일 초과
                dp[i] = dp[i + 1];
        }

        System.out.println(dp[1]);
    }
}



Python Code

# -*- coding: utf-8 -*-
 
import sys
 
def solve(n, t, p):
    dp = [0 for i in range(n)]
    
    ## 초기값
    ## 1일간만 상담해야 들어갈 수 있음
    if t[n-1] == 1:
        dp[n-1] = p[n-1]
 
    ## 뒤에서부터 계산함
    for i in range(n-2, -1, -1):
        day = i + t[i]
 
        ## 상담가능일이 n이랑 똑같으면 이후엔 상담불가능
        if day == n:
            dp[i] = max([p[i], dp[i+1]])
        ## 상담 가능일이 n보다 작으면 이후에 상담가능
        elif day < n:
            dp[i] = max([p[i] + dp[day], dp[i+1]])
        elif day > n:
            dp[i] = dp[i+1]
 
    print(dp[0])
 
if __name__ == '__main__':
    n = int(sys.stdin.readline())
    t = []
    p = []
 
    for i in range(n):
        ti, pi = map(int, sys.stdin.readline().split())
        t.append(ti)
        p.append(pi)
 
    solve(n, t, p)


+ Recent posts