Algorithm

[백준][python]14501 퇴사

soduddl1 2023. 5. 10. 19:22

문제

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

소스코드1 : DFS

import sys
input = sys.stdin.readline

if __name__ == "__main__":
    n = int(input())
    schedule = [list(map(int,input().split())) for _ in range(n)]
    visited = [False for _ in range(n)]
    res = 0

    def dfs(today, total,lastdaypay):
        global res
        if today > n:
            res = max(res,total-lastdaypay)
            return
        elif today == n:
            res = max(res,total)
            return

        for i in range(today,n):
            if not visited[i]:
                visited[i] = True
                dfs(i + schedule[i][0], total + schedule[i][1],schedule[i][1])
                visited[i] = False

    dfs(0,0,0)
    print(res)

설명

n이 15개뿐이 안되서 백트래킹을 이용해서 DFS 탐색을 했다

오늘 날짜 + 상담 날짜가 퇴사일을 넘어버리면 그 전 잡은 상담은 하지 못하므로 total에서 lastdaypay(직전 더해준 값)을 빼버린다

오늘 날짜 + 상담 날짜가 퇴사일이면 상담을 할 수 있으므로 total을 계산해준다.

 

소스코드 2 : DP

if __name__ == "__main__":
    n = int(input())
    arr = [list(map(int,input().split())) for _ in range(n)] #상담에 걸리는 시간, 상담 비용
    dp = [0] * (n+1)

    for day in range(n-1,-1,-1):
        if day + arr[day][0] > n : #현재 날짜와 상담 날짜를 더해서 퇴사날이면
            dp[day] = dp[day+1] # 그동안 누적된 비용을 그대로 가져감
        else:
            dp[day] = max(dp[day+1],dp[day+arr[day][0]] + arr[day][1]) #상담을 했을 때 비용과 상담 안했을 때 지금까지 누적값중 더 큰 값으로 교체

    print(dp[0])

설명

bottom-up 방식으로 누적값을 더해 가장 마지막날부터 체크해서 첫번째 값이 최종 누적 값이다.

0부터 하면 안되는 이유는 0일 일 때 5일을 상담하면 누적하다 5일이 오면 누적된 최종 값이 5일이 포함된 값인지 아닌지 알 수 가 없다

마지막날 부터 체크해주면 dp를 구할 때 중복되는 값을 제거해줄 수 있다.

dp[day] = max(dp[day+1],dp[day+arr[day][0]] + arr[day][1])
  • 이전에 누적된 값
  • 오늘 날짜에 상담한 날짜를 더한 날의 pay + 오늘 상담을 하고 받은 pay

을 비교해서 더 큰 값을 dp 에 넣어줌으로써 중복된 값을 제거할 수 있다.

dp를 저장하는 내용을 표에 그려보면 아래와 같다.

 

7일일 때, 7 + 2 는 퇴사 날짜가 지나므로 그 전까지의 pay를 가져온다

6일일 때, 6 + 4 는 퇴사 날짜가 지나므로 그 전까지의 pay를 가져온다

5일일 때, 5 + 2 는 퇴사전이므로 상담을 할 수 있다. 그전까지의 누적합오늘 pay + (5+2)일의 누적 pay 중 큰 값을 가져온다. 

위와 같은 방식으로 체크하면 최종 1일에 있는 값이 중복이 되지 않고 가장 돈을 많이 받고 상담을 하는 금액이 된다.