[Year-Dream 스터디 12주차 : 동적계획법, Python] - 거스름돈 주기

2021, Nov 01    


이어드림 12주차 알고리즘 스터디 문제 : 거스름돈 주기(상)



Solution


정답 코드

import sys
# from collections import defaultdict
input = sys.stdin.readline

n = int(input())
coins = list(map(int, input().split()))
# coins.sort(reverse=True)
change = int(input())
 
DP = [0 for _ in range(change+1)]

DP[0] = 1

for c in coins:                 
    for i in range(1, change+1):        # 특정 동전만 사용해서 지불하는 경우
        if i - c >= 0:
            DP[i] += DP[i - c]
            
print(DP)


오답 코드


for i in range(1, change+1):
    for c in coins:           # 동일한 케이스가 누적해서 더해짐
        if i - c >= 0:
            DP[i] += DP[i-c]


풀이과정 및 느낀점


이 문제의 관건은 DP에 거스름돈 주는 경우의 수가 누적해서 더해지는 걸 방지하는 것이다.
처음에는 오답 코드처럼 문제를 풀었는데 이렇게 하면 특정 금액 자체가 기준이 돼고(첫 번째 for 문) 거스름돈 경우의 수 계산은 이후에 이뤄져서(두 번째 for 문) 거스름돈을 10 -> 50 한 경우와 50 -> 10 준 경우가 중복돼서 계산된다.
따라서, 위의 정답코드처럼 for 문의 순서를 뒤바꿔 각 단위의 거스름돈을 사용해 지불 가능한 금액들을 먼저 DP 에 다 저장하는 식으로 수정하게 되면 중복계산없이 DP를 완성할 수 있다.