알고리즘
[Python] BOJ no.9084 동전
후리붜너
2023. 4. 15. 16:26
문제 링크
https://www.acmicpc.net/problem/9084
9084번: 동전
우리나라 화폐단위, 특히 동전에는 1원, 5원, 10원, 50원, 100원, 500원이 있다. 이 동전들로는 정수의 금액을 만들 수 있으며 그 방법도 여러 가지가 있을 수 있다. 예를 들어, 30원을 만들기 위해서는
www.acmicpc.net
문제 설명
9084, 동전 문제는 주어지는 동전의 단위로 어떤 금액을 만들 수 있는 개수를 구하는 프로그램을 작성하면 된다. 다이나믹 프로그래밍(DP) 유형의 알고리즘으로 이전의 값들을 사용해 문제에서 요구하는 금액을 만들 수 있는 조합의 개수를 구하면 된다.
내 풀이
DP를 사용하야 풀 수 있다는 생각은 하고 있었고, 비슷한 Logic을 떠올리는데는 성공했다. 하지만 구체적인 코드가 생각나지 않았다.. ㅜㅜ
풀이 #1
t = int(input())
for _ in range(t):
n = int(input())
coins = list(map(int, input().split()))
m = int(input())
d = [0] * (m+1)
d[0] = 1
for coin in coins:
for i in range(coin, m+1):
d[i] += d[i-coin]
print(d[m])
- 먼저 테스트 케이스 개수를 받아온다. (t)
- 테스트 케이스 별로 동전 단위의 개수(n), 화폐가 되는 동전 리스트(coins), 목표 금액(m)을 받아온다.
- DP공간(d)을 만들어주고 (초기에는 모든 금액을 만드는 개수를 0으로 초기화) 0원을 만들기 위한 개수는 1개이므로 'd[0] = 1'을 넣어준다.
- for 문을 도는데 '에라토스테네스의 체' 알고리즘처럼 가장 작은 coin부터 만들 수 있는 값들을 모두 채워준다.
- 예시로 coin은 5, 7이 있고 목표금액은 22라고 해보자.
- 먼저 5부터 for문을 시작해보면, 5는 0 + 5로 1가지, 10은 5(직전의 0 + 5 ) + 5로 1가지, 15는 1가지... 이런식으로 0에 의한 5의 배수들이 1가지 방법으로 추가가 된다.
- 이후 7에 대해 진행해보자. 먼저 기존 1가지를 가지고 있는 0에 7을 더한 7에 1가지, 5에 1가지를 가지고 있으니 12 (5 + 7)에 1가지, 계속해서 14 (7 + 7), 17 (10 + 7), 19 (12 + 7), 22 (17 + 5) 이런식으로 가지고 있는 방법수를 계승해서 가지고 올라가고 만약 다른 방법에 추가가 되더라도 중복적으로 해당 값은 추가가 되므로 만족할 수 있다. (5와 7의 배수 35 -> 5로만 35 만드는 1가지 + 7로만 35 만드는 1가지 = 2가지)
이 문제를 푸는 방법에 대해서 고민했을 때 이전값에 coin만큼 증가한 dp 공간에 더해줘야겠다는 생각은 했지만 만약 1이 아닌 2,3,4 와 같은 큰 값을 가지고 있을 때는 그 값을 만드는 방법의 개수를 단순히 더하는 것으로 만족시킬 수 있을지 고민하게 되었다.
예를 들어, coin은 1,2이라면 3을 만드는 방법은 2가지(1+1+1, 1+2)이다. 그럼 위의 알고리즘으로 3을 채워보자.
d[3] = 0, d[3] += d[2](coin=1), d[3] += d[1](coin=2)
먼저, d[3]을 1로 채우는 경우에는 1+1(2) +1인 1가지가 추가되고 2로 채우는 경우는 1 + 2인 1가지가 추가되어 2가지가 된다.
이때, coin이 오름차순으로 계산되는 것을 고려하지 않고 모두 계산한다면 d[2] + 1의 과정에서 d[2]는 2 (1+1, 2)이기 때문에 d[3]을 3으로 잘못 계산할 수 있다. (즉, 2 중 for문의 순서도 고려해야한다. -> 둘이 바뀐다면 위의 문제가 발생할 수 있음)