Problem Solving/Baekjoon

[boj] 14501번: 퇴사

kimdozzi 2023. 2. 16. 09:31

출처 : https://www.acmicpc.net/problem/14501

 

14501번: 퇴사

첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다.

www.acmicpc.net

 

 

 

1. 문제 설명 

백준이는 퇴사를 하려고 한다. 오늘부터 N+1일째 되는 날 퇴사를 하기 위해서 남은 N일 동안 최대한 많은 상담을 하려고 한다. 최대 수익을 구하라.

 

 

 


2. 접근 방식 

dp로 접근했다. dp = new int[n+1]로 초기화해서 N+1일째 되는 날까지 값을 갱신해준다. 각 0일부터 N일까지 반복하면서 '현재 요일까지 벌어들인 수익 + 현재 상담을 시작해서 끝나는 날에 받는 수익' 과 '끝나는 날에 벌어들인 수익'을 비교한다.

 

for(int i = 0; i < n; i++) 

    for(int j = i + arr[i].time; j < n+1; j++)

        if(dp[j] < dp[i] + arr[i].profit)

            dp[j] = dp[i] + arr[i].profit

 

 

예를 들어보자. dp = [0, 0, 0, 0, 0, 0, 0, 0] 일 때, 1일에 상담을 시작해서 3일 뒤에 끝나면 4일이 된다. 1일에 상담을 시작해 4일에 상담을 끝냈을 때(dp[0] + arr[0].profit) 가지고 있는 수익은 0 + 10 = 10원(편의상 원으로 가정)이다. 그리고 4일에 갖고 있던 수익(dp[3]) 과 비교한다. 0 < 10 이므로 dp[3]의 배열은 10으로 갱신된다. 그 뒤의 요일들도 모두 0이기 때문에 N+1일까지 10으로 갱신될 것이다. 

 

현재 1일에 상담을 시작했을 경우의 수익을 갱신한 상태다.             

dp = [0,   0,   0,   10,  10,    10,    10,      10]                                            

        1일 2일 3일 4일  5일  6일  7일(N일)  N+1일

 

2일에 상담을 시작한 경우, 2일에 상담을 시작하면 5일 뒤에 수익을 얻을 수 있다. 

dp[1] + dp[1].profit > dp[6] 을 비교해보면 20 > 10 이 된다. 이런 식으로 계속 갱신해준다.

.

.

.

5일차의 상담을 하는 경우를 살펴본다. 현재 4일차까지 갱신된 dp배열은 [0, 0, 0, 10, 30, 30, 30, 30] 이다.

현재(5일차)까지 벌어들인 최대 수익은 30원이다. 5일차에 상담을 시작한다면 2일이 걸리고 수익은 15원을 얻을 수 있다. 5일차에 상담을 시작해서 7일 차에 벌 수 있는 수익(15) + 5일차까지 벌어들인 수익(30) > 7일차까지 벌어들인 수익(30) 은 45로 갱신된다. 최종적인 dp 배열은 [0, 0, 0, 10, 30, 30, 45, 45]가 된다. 마지막 N+1일째가 되었을 때까지 벌어들인 수익을 출력해주자 !

 

 


3. 주석 달기 (변수 설명, 각 줄마다 문장으로 설명, 함수 설명)

package samsungCodingTest.Week04;

import java.io.*;
import java.util.StringTokenizer;

public class BOJ14501 {
    static class Pair<T, P> { // pair 클래스 구현 Time, Profit을 받기 위해
        T time;
        P profit;

        public Pair(T timeValue, P profitValue) {
            time = timeValue;
            profit = profitValue;
        }
    }
    static Pair<Integer, Integer>[] arr; 
    static int n ;
    static int[] dp;

    static FastReader scan = new FastReader();

    public static void main(String[] args) throws IOException {


        n = scan.nextInt(); 
        dp = new int[n+1]; // N+1일만큼의 dp 배열
        arr = new Pair[n+1]; // N+1개의 상담완료 기간, 받을 수 있는 금액을 저장하기 위한 배열
        for (int i = 0; i < n; i++) {
            int t = scan.nextInt(), p = scan.nextInt();
            arr[i] = new Pair<>(t, p); // Use dynamic arr of pairs.
        }
        for (int i = 0; i < n; i++) {
            for (int j = i + arr[i].time; j < n+1; j++) {
                if (dp[j] < dp[i] + arr[i].profit)
                    dp[j] = dp[i] + arr[i].profit;
            }
        }
        System.out.println(dp[dp.length-1]);
    }
    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public FastReader(String s) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(new File(s)));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

 

 


4. 분석 및 시간복잡도 

시간복잡도 : O(N^2) 

 

dp 테이블을 정의하는 연습을 많이 해야겠다.. 아직 dp는 쉽지 않다..