반응형
문제
N가지 종류의 화폐 중에서 화폐의 개수를 최소한으로 이용해 그 가치의 합이 M원이 되도록 한다. (화폐 개수는 무제한이며 순서가 달라도 같은 걸로 친다)
입력 조건
- 첫째 줄에 N, M이 주어진다. (1 <= N <= 100, 1 <= M <= 10,000)
- 이후 N개의 줄에는 각 화폐의 가치가 주어진다. 화폐 가치는 10,000보다 작거나 같은 자연수이다.
출력 조건: 첫째 줄에 M원을 만들기 위한 최소한의 화폐 개수를 출력한다 (불가능할 때는 -1을 출력한다).
정답 코드
import sys
n, m = map(int, sys.stdin.readline().rstrip().split())
cost = [int(sys.stdin.readline().rstrip()) for i in range(n)]
d = [10001] * (m + 1)
d[0] = 0
for i in range(n):
for j in range(cost[i], m + 1):
if d[j - cost[i]] != 10001:
d[j] = min(d[j], d[j - cost[i]] + 1)
if d[m] == 10001:
print(-1)
else:
print(d[m])
DP 문제이다 보니까 핵심은 점화식을 세우는 것이다.
예를 들어 현재 화폐 단위가 2와 3이 있다고 가정하면 m을 만드는 최소 개수는 m - 2를 만드는 최소 개수와 m - 3을 만드는 최소 개수 중 더 작은 값에 1을 더한 값이 된다. 이를 점화식으로 나타내면 d[j] = min(d[j], d[j - cost[i]] + 1)으로 나타낼 수 있다.
m의 최대 크기가 10,000이므로 만들 수 없는 경우를 나타내는 수로 10,001을 사용하여 초기 dp 리스트를 초기화해준다.
그다음 첫 번째 화폐부터 차례대로 확인하면서 dp 리스트를 갱신해나가면 된다.
배울 점
처음 이 문제를 봤을 때 그리디의 대표 문제인 거스름돈 문제가 생각이 났다. 하지만 화폐 단위에서 큰 단위가 작은 단위의 배수일 때만 그리디로 풀 수 있다는 조건을 확인하고 dp로 접근하기 위해 노력했다.
dp 문제를 계속 풀고 있지만 항상 풀이를 참고해야 할 정도로 점화식을 생각해내고 구현하는 것이 너무 어렵게 느껴진다.
다양한 문제를 접해보면서 더 노력해야겠다.
참고자료: 이것이 취업을 위한 코딩 테스트다 with 파이썬 - 나동빈 지음(한빛미디어)
반응형
'알고리즘 > 이취코테' 카테고리의 다른 글
[이취코테] 금광 (0) | 2022.02.08 |
---|---|
[이취코테] 개미 전사 (0) | 2022.02.06 |
[이취코테] 미로 탈출 (0) | 2022.01.14 |
[이취코테] 음료수 얼려 먹기 (0) | 2022.01.14 |
[이취코테] 문자열 재정렬 (0) | 2022.01.05 |