728x90
반응형
14501번 퇴사 (DP)
1. 문제
https://www.acmicpc.net/problem/14501
N일 동안 상담 일정을 받았고, 각 날짜마다 상담을 진행하면 걸리는 시간과 받을 수 있는 금액이 주어진다.
- 퇴사 전까지 최대한 많은 상담을 수행하여 최대 수익을 얻고자 한다.
- 단, 상담은 중복되게 진행할 수 없으며, 퇴사일 이후까지 걸리는 상담도 진행할 수 없다.
입력
- 첫째 줄에 N (1 ≤ N ≤ 15)
- 둘째 줄부터 N개의 줄에 걸쳐, 각 날에 대한 상담 기간 T와 수익 P가 주어진다.
출력
- 최대 수익을 출력한다.
문제 접근 방법
- 수익을 최대화하는 문제이므로, 완전탐색 or DP를 고려
- "오늘 상담을 한다 vs 하지 않는다" 두 가지 선택지를 모든 날에 대해 고려해야 하므로 브루트포스 기반의 DP가 적절함
- 상담을 하면 i + T일에 다음 선택 가능, 즉 상태 전이 시 다음 인덱스는 유동적
- ⭐️ 각 날짜를 기준으로 최대 수익을 저장하는 1차원 DP 배열 사용 ⭐️
2. 풀이 과정
🔍 문제 분석
- i번째 날에 상담을 할 수 있는 경우:
i + T[i] ≤ N
이어야 함 (퇴사일 전까지 완료)- 그때 수익은
P[i]
이며, 해당 상담 이후부터 다음 상담을 진행 가능
- i번째 날에 상담을 하지 않는 경우:
- 이전까지의 수익을 다음 날로 이어감
DP 배열 구조
dp[i]
: i일까지 얻을 수 있는 최대 수익- 초기값은 모두 0으로 설정
알고리즘 핵심 로직
for i in range(n)
로 날짜를 순회하면서:- 상담을 할 수 있다면,
dp[i + T[i]] = max(dp[i + T[i]], dp[i] + P[i])
- 상담을 하지 않더라도,
dp[i + 1] = max(dp[i + 1], dp[i])
- 상담을 할 수 있다면,
dp[n]
에는 퇴사일까지 누적된 최대 수익이 저장됨
3. 코드
import sys
input = sys.stdin.readline
n = int(input())
schedule = [list(map(int, input().split())) for _ in range(n)]
# dp[i] = i일까지의 최대 수익
dp = [0] * (n + 1)
for i in range(n):
t, p = schedule[i]
# 상담을 할 수 있는 경우
if i + t <= n:
dp[i + t] = max(dp[i + t], dp[i] + p)
# 상담을 하지 않는 경우 (그대로 수익 유지)
dp[i + 1] = max(dp[i + 1], dp[i])
print(dp[n])
✅ 최적화 포인트
dp[i]
→ i일까지 최대 수익을 저장하여, 상담 여부 결정에 사용- 불필요한 중복 연산 없이 한 방향으로만 순회 (i는 오직 증가)
- 배열 복사 없이 상태 갱신 → 공간 효율성도 좋음
✅ 시간 복잡도
- O(N): 단일 for 루프에서 최대 N번 상태 갱신
- N이 최대 15이므로 시간 여유 충분
4. 결과
이 문제의 핵심은 "상담을 할 수 있는지 판단하고, 한다면 그 다음 날짜로 점프하는 방식"이었고,
이를 DP 배열로 관리하여 최적의 수익 경로를 빠르게 구하는 것이 중요했다.
728x90
반응형