이 글은 어떤 과정을 통해 해당 문제를 풀고 이해할 수 있었는지를 정리하기 위해 작성하였습니다!
https://www.acmicpc.net/problem/15486
🚨 단, N+1일 전에 일을 시작했어도 마무리가 N+1이후까지 진행되는 것이면, 수익으로 인정하지 X
N+1일에 퇴사를 함 -> N일까지 일을 마무리 지어야 함
예시가 이렇게 된다고 했을 때, 7일에 끝을 내야 한단 것이다.
7
3 10
5 20
1 10
1 20
2 15
4 40
2 200
7일차의 상담은 7+2 = 9로 7을 초과 (x)
6일차의 상담은 6+4 = 10으로 초과 (x)
5일차의 상담은 5+2 = 7로 초과하지 않음 (⭕)
그렇게 되면 dp[5]에는 우리는 최댓값을 구해야 되기 때문에, 가장 큰 최댓값이 들어가야 한다.
p[5] + 5일까지 벌어들인 dp값, 혹은 지금까지의 값 중 최댓값 이들 중 더 큰 값이 기록되게 된다.
dp[i] = max(p[i] + dp[t[i] + i], max값)
5일차에 dp[5] = p[5] + dp[7]이 되는데, dp[7]은 아직 갱신된 적이 없어 값이 0이 된다.
=> dp[5] = 15
다음으로 최댓값을 갱신하여 max_value = dp[5] = 15가 된다.
4일차도 1일이 걸리므로 진행가능하다.
dp[4] = p[4] + dp[t[4] + 4] = p[4] + dp[5] = 20 + 15=35이다.
3일차도 1일이 걸리므로 진행됨.
dp[3] = p[3] + dp[t[3] + 3] = p[3] + dp[4] = 10 + 35 = 45
2일차는 5일이 진행된다. 가능하다. 2+5 = 7일차니까!
dp[2] = p[2] + dp[t[2] + 2] = p[2] + dp[7] = 20 + 0 = 20
1일차는 4일이 진행된다. 가능하다 -> 1+4 = 5일차니까
dp[1] = p[1] + dp[t[1] + 1] = p[1] + dp[4] = 10 + 35 = 45
라고 생각할 수 있는 이들에게
우리는 역순으로 계산을 하고 있기 때문에 여기서의 기준으로 이전 값이란 우리의 뒤에 값들이란 것을 잊지말자!
제출했을 때는 N의 값을 신경쓰지 않아서 '퇴사'와 같이 풀었더니 시간초과가 떴다.😢
'''
[DP] 퇴사2 (골 5)
조건 : n일까지만 근무
goal: 백준이가 얻을 수 있는 최대 수익을 구하라
'''
import sys
input = sys.stdin.readline
n = int(input())
t = []
p = []
dp = [0] * (n + 1)
for _ in range(n):
ti, pi = map(int, input().rstrip().split())
t.append(ti)
p.append(pi)
#idx + t = 가능한 날의 idx
#idx 날 근무를 할지, pass 할지
'''
최대이익
t가 지나가
'''
for idx in range(n-1,-1,-1):
#퇴사날을 넘긴다(진행할 수 x)
if idx + t[idx] > n:
dp[idx] = dp[idx + 1] #(최댓값,0)을 그대로 저장
else:
#다른경우를 방문한 dp vs 그 직전 방문한 dp를 비교 후 -> 최댓값을 삽입
# 목표는 최댓값을 가지도록 해야함
dp[idx] = max(p[idx] + dp[t[idx]+idx], dp[idx+1])
#최종적으로 최댓값을 출력할 수 밖에 없음
print(dp[0])
결과적으로 대량의 데이터를 최적화하기 위해 '입력시간을 줄였다'
sys.stdin.readline
을 이용하여 해결했다.
그러나 시간이 꽤나 걸린 것을 알 수 있었다..
좀 더 시간이 덜 걸리고 다른 방식으로 푸신 분들이 궁금했다.
그래도 다른 방법을 더 확인하고 싶어 다른 분들의 코드를 참고했다.
import sys
input = sys.stdin.readline
n = int(input())
t, p = [0 for _ in range(n + 1)], [0 for _ in range(n + 1)]
for i in range(1, n + 1):
t[i], p[i] = map(int, input().split())
dp = [0 for _ in range(n + 1)]
for i in range(1, n + 1):
dp[i] = max(dp[i], dp[i - 1]) # 이전까지의 최댓값
fin_date = i + t[i] - 1 # 당일 포함
print("i값", i, "findate = ", fin_date)
if fin_date <= n: # 최종일 안에 일이 끝나는 경우
# i일부터는 일을 해야하므로 i일에 얻을 수 있는 최댓값이 아닌 i-1일까지 얻을 수 있는 최댓값을 구한다
dp[fin_date] = max(dp[fin_date], dp[i - 1] + p[i])
print(max(dp))
시간 복잡도가 비슷하단 것을 알 수 있었다. 이를 줄이기 위해서는 계산 부분에서 불필요한 계산을 줄일 수 있도록 수정하는 것이 가장 best인 것 같다.