(Java) 백준 14501번 - 퇴사

코딩너구리·2026년 2월 6일

코딩 문제 풀이

목록 보기
204/266

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

문제

> 상담원으로 일하고 있는 백준이는 퇴사를 하려고 한다.
> 오늘부터 N+1일째 되는 날 퇴사를 하기 위해서, 남은 N일 동안 최대한 많은 상담을 하려고 한다.

> 백준이는 비서에게 최대한 많은 상담을 잡으라고 부탁을 했고, 
비서는 하루에 하나씩 서로 다른 사람의 상담을 잡아놓았다.

> 각각의 상담은 상담을 완료하는데 걸리는 기간 Ti와 상담을 했을 때 받을 수 있는 금액 Pi로 이루어져 있다.

> N = 7인 경우에 다음과 같은 상담 일정표를 보자.

 	1일	2일	3일	4일	5일	6일	7일
Ti	3	5	1	1	2	4	2
Pi	10	20	10	20	15	40	200

> 1일에 잡혀있는 상담은 총 3일이 걸리며, 상담했을 때 받을 수 있는 금액은 10이다.
> 5일에 잡혀있는 상담은 총 2일이 걸리며, 받을 수 있는 금액은 15이다.

> 상담을 하는데 필요한 기간은 1일보다 클 수 있기 때문에, 모든 상담을 할 수는 없다. 
> 예를 들어서 1일에 상담을 하게 되면, 2일, 3일에 있는 상담은 할 수 없게 된다.
> 2일에 있는 상담을 하게 되면, 3, 4, 5, 6일에 잡혀있는 상담은 할 수 없다.

> 또한, N+1일째에는 회사에 없기 때문에, 6, 7일에 있는 상담을 할 수 없다.

> 퇴사 전에 할 수 있는 상담의 최대 이익은 1일, 4일, 5일에 있는 상담을 하는 것이며, 
이때의 이익은 10+20+15=45이다.

> 상담을 적절히 했을 때, 백준이가 얻을 수 있는 최대 수익을 구하는 프로그램을 작성하시오.

접근

dp를 사용하여 해당 날짜에 각각 얼마나 벌 수 있나를 계산해 나간다.
각 날에 대해, 일을 할 떄와 안할 때로 나눠줘야한다.
먼저 오늘 일을 안하게 되면 내일 내가 번 돈은 어제 번돈+0, 오늘 번돈 중에 더 큰돈이 된다. 일을 안한 경우는 내가 다른 날 잡은 상담 때문에 해당 일에 일을 못할 경우를 말한다.
이제 일을 하면 내가 3일째 떄 2일짜리 일을 하면 5일 째 되는날 번 돈은 3일째까지 번돈 + 2일짜리일, 기존에 5일 째 벌어놨던 돈 중 더 큰 돈이 된다. 여기서 기존에 5일 돈은 다른 경우인 2일 째에서 3일짜리일을 헀다거나, 1일째에서 4일 짜리일은 한경우가 된다.
이렇게 모두 일자별 번 돈을 구하고 그 중 가장 돈을 많이 번 일자를 골라 출력한다.

문제해결

> 상담이 퇴사일인 N+1일에 끝나는 경우도 가능하므로 크기를 16으로 주는데 일을 안한 경우를 위해 +1일 해서 17일로 준다.
> Ti와 Pi를 입력받고 먼저 일을 안한 경우를 따져준다.
> 다음날의 번돈 dp(i+1)은 dp(i)와 dp(i+1)중 더 큰 돈이다.
> 이제 일 할 경우를 따지전 i+Ti가 N+1보다 커질때, 즉 상담이 퇴사날 이후 끝날 경우를 제해준다.
> 이제 해당 상담을 했을 때, 끝나는 날에 버는 돈은 현재날 + 해당 상담의 비용과 그날 끝나기로 예정됐던 다른 경우의 수들 중 더 큰 값이다.
> 모든 일자 중 가장 많은 돈을 버는 일자의 금액을 출력한다.

코드

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

public class Main {
    //14501번 퇴사
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int[] dp = new int[17];
        for(int i = 1; i <= N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int Ti = Integer.parseInt(st.nextToken());
            int Pi = Integer.parseInt(st.nextToken());

            dp[i+1] = Math.max(dp[i], dp[i+1]);
            if(i + Ti > N+1) continue;
            dp[i+Ti] = Math.max(dp[i] + Pi, dp[i+Ti]);

        }
        int rst = 0;
        for(int i : dp) rst = Math.max(rst, i);
        System.out.print(rst);
    }
}

후기

일을 안하고 넘긴다 라는 개념을 빼먹어서 헤맸다.

0개의 댓글