In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation:
1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p).
It is possible to make £2 in the following way:
1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p
How many different ways can £2 be made using any number of coins?
-
재귀를 활용하는 전형적인 문제이다..
-
편의상 1페니와 2페니로 5페니를 만드는 경우의 수를 생각해보자.
- 1 페니 : 1가지
- 2 페니 : (1+1), (2)
- 3 페니 : (1+1+1), (1+2)
- 4 페니 : (1+1+1+1), (1+1+2), (2+2)
- 5 페니 : (1+1+1+1+1), (1+1+1+2) \(\cdots \\\)
-
위의 식은 아래의 공식을 따른다.
- \[\begin{align} f\left(1\right) =&\ 1\\ f\left(2\right) =&\ 2 \\ f\left(3\right) =&\ 1+ f\left(1\right) \\ f\left(4\right) =&\ 1+ f\left(2\right) \\ f\left(5\right) =&\ 1+f\left(3\right) \\ \end{align}\]
-
def euler031a(value=200): coins = [1, 2, 5, 10, 20, 50, 100, 200,] def solution(val=200,index=7): if val < 0: return 0 if val == 0: return 1 if index < 0: return 0 return solution( val-coins[index], index) + solution(val, index-1) print(solution(val=value))
-
정말 단순하게 재귀로 구성하였다. 작동은 하지만 생각보다
(라기보다는 당연히)빠르진 않다.def euler031(): coins = (1, 2, 5, 10, 20, 50, 100, 200) ways = [1]+[0] * 200 for coin in coins: for i in range(coin, 200+1): ways[i] = ways[i] + ways[i-coin] print(ways[-1])
-
그래서 dp(맞나..)의 방식으로 다시 구성해봤다.
-
우선 모든 방법의 갯수를 저장할 배열을 생성한다(계산하려고 하는 돈의 크기만큼).
-
그리고 ways의 index에 해당하는 돈의 경우의 수를 저장해야한다.
-
1페니를 사용할 경우 2페니는 (1페니 + 1페니) 3페니는 (1페니 + 1페니 + 1페니)페니이다. 4페니는 (1페니 + 1페니 + 1페니 + 1페니)페니이다.
이 시점에서 배열에는 (1,1,1)이 저장되어 있다
-
(1,1,1,1,1)의 의미는 1페니로 1페니,2페니 3페니를 만드는 갯수이고 이것을 연결해서
-
2페니를 활용해서 배열을 채워보면 2페니 부분에 이미 저장되어 있는 수치에 2페니로 2페니를 만드는 방법은 1가지 밖에 없으므로 +1한다. 여기서 우리는 이 처리를 0번 index에 저장된 1을 사용한다. 그리고 3페니로 이동하여 이미 (1+1+1)이 저장되어 있는 1에 (1+2)의 경우의 수를 추가한다. 역시나 지금 2페니와 조합이 되어지는 1의 경우의 수를 필요로 하므로 지금의 index에 페니를 빼준 곳의 경우의 수를 합쳐준다. 마지막으로 4페니로 이동하여 (1+1+1+1)의 경우의 수가 저장되어 있는 곳에 (2+2)와 (1+1+2)의 경우의 수를 추가해주는데 이 경우의 수는 우리의 지금 2페니에 2페니와 (1+1)의 경우의 수를 합치는 것이다. 밑줄 친 곳의 경우의 수는 우리가 2페니를 구할떄 만들어둔 경우의 수이므로 지금 index에 -2를 하면 얻어올 수 있다.
-
-
- 머리로는 이해하는데 말로 설명이 조금 부족하다. 추후 설명 보완을..