<청춘> 격정적으로 사는 것

밤을 새고 공부한 다음 날 새벽에 느꼈던 생생한 환희와 야생적인 즐거움을 잊을 수 없다

코딩테스트

[다이나믹 프로그래밍 / 동적계획법] 실전 문제 <5> 효율적인 화폐 구성 / 이것이 취업을 위한 코딩테스트다 with 파이썬

수학도 2021. 7. 26. 17:24

효율적인 화폐 구성

N가지 종류의 화폐가 있다.

이 화폐들의 개수를 최소한으로 이용해서 그 가치의 합이 M원이 되도록 하려고 한다.

이때 각 화폐는 몇 개라도 사용할 수 있으며, 사용한 화폐의 구성은 같지만 순서만 다른 것은 같은 경우로 구분한다.

예를 들어 2원, 3원 단위의 화폐가 있을 때는 15원을 만들기 위해 3원을 5개 사용하는 것이 가장 최소한의 화폐 개수이다.

 

입력 조건

첫째 줄에 N, M이 주어진다. (1≤N≤100, 1≤M≤10,000)

이후 N개의 줄에는 각 화폐의 가치가 주어진다. 화폐 가치는 10,000 보다 작거나 같은 자연수이다.

 

출력 조건

첫째 줄에 M원을 만들기 위한 최소한의 화폐 개수를 출력한다.

불가능할 때는 -1을 출력한다.

 

입력 예시1

2 15

2

3

 

출력 예시1

5

 

입력 예시2

3 4

3

5

7

 

출력 예시2

-1

 

코드

N, M = map(int, input().split())
array = []
for i in range(N):
    array.append(int(input()))

d = [10001] * (M+1)  # M의 최대 크기가 10,000이므로 10001 로 초기화

d[0] = 0  # 0원을 만드는 방법은 화폐를 하나도 쓰지 않는 경우이므로 0
for i in range(N):
    for j in range(array[i], M + 1):
        d[j] = min(d[j], d[j - array[i]] + 1)


if d[M] == 10001:
    print(-1)
else:
    print(d[M])

 

해설

예를 들어 array = [2, 3, 5], M = 7 일 때

★ 화폐 단위 2 (i=0):
i = 0, j = array[0] = 2
	d[j] = d[2] = 10001
	d[j - array[i]] + 1 = d[2 - array[0]] + 1 = d[2 - 2] + 1 = d[0] + 1 = 1
	d[2] = min(10001, 1) = 1
i = 0 , j = 3
	d[j] = d[3] = 10001
	d[3 - 2] + 1 = d[1] + 1 = 10002
	d[3] = min(10001, 10002) = 10001
i = 0, j = 4 : d[4] = d[4 - 2] +1 = 2
i = 0, j = 5 : d[5] = 10001
i = 0, j = 6 : d[6] = d[6 - 2] + 1 = 3
i = 0, j = 7 : d[7] = 10001

★ 화폐 단위 3 (i=1)
i = 1, j = array[1] = 3
	d[3] = min(10001, d[3 - 3] + 1) = 1
i = 1, j = 4 : d[4] = min(2, 10002) = 2
i = 1, j = 5 : d[5] = min(10001, 2) = 2
i = 1, j = 6 : d[6] = min(3, 2) = 2
i = 1, j = 7 : d[7] = min(10001, d[4] + 1) = 3