|
| 1 | +# Cambio de monedas |
| 2 | + |
| 3 | +#### Declaración de problema |
| 4 | +Dado un valor `N`, si queremos hacer un cambio para los centavos `N`, y tenemos una oferta infinita de cada una de las monedas valoradas `S = {S1, S2, .. , Sm}`, ¿cuántas maneras podemos hacer el cambio? El orden de las monedas no importa. |
| 5 | + |
| 6 | +#### Enfoque |
| 7 | + |
| 8 | +Deje que el `dp[i]` sea la longitud del cambio de moneda del prefijo `N[1..i]`. Nuestra respuesta es `dp[N]`. |
| 9 | +Llenamos `dp[0]` como 1 porque sólo hay una manera de conseguir 0 monedas (No recogemos monedas). |
| 10 | + |
| 11 | +Ahora vamos a tratar de calcular `dp[i]` para cualquier `i`. `dp[0..i]` almacenará cada sub-problema de `0` a `N`. Es por eso que la respuesta será `dp[N]`. En primer lugar, necesitamos iterar cada tipo de moneda para elegirlos uno por uno. Luego iteramos los sub problemas de la moneda actual que recogemos antes a los centavos `N`. Es por eso que debemos hacer la tabla dp con columnas `N`. |
| 12 | + |
| 13 | +Estos son los códigos para el algoritmo coin change: |
| 14 | +``` |
| 15 | + para coin_val en S: |
| 16 | + para i en rango (coin_val, n + 1): |
| 17 | + dp[i] += dp[i - coin_val] |
| 18 | +``` |
| 19 | + |
| 20 | +En la segunda iteración, por cada centavo que se puede intercambiar, lo tomamos restando la columna enésima por el valor de la moneda que tomamos y añadiéndolo a la columna actual. Así que `dp[i]` almacenará el sub problema actual. |
| 21 | + |
| 22 | +#### Complejidad horaria |
| 23 | + |
| 24 | +`O(N * S)` - en cualquier caso |
| 25 | + |
| 26 | +#### Complejidad espacial |
| 27 | + |
| 28 | +`O(N)` - implementación simple. Sólo necesitamos arreglos de discos 1D para almacenar la respuesta. |
| 29 | + |
| 30 | +#### Ejemplo |
| 31 | + |
| 32 | +Digamos que tenemos 3 tipos de monedas `[1,2,3]`, y queremos cambiarlas por 7 centavos. Así que definiremos nuestra mesa así: |
| 33 | + |
| 34 | +``` |
| 35 | +[1, 0, 0, 0, 0, 0, 0, 0] |
| 36 | +``` |
| 37 | + |
| 38 | +0ª columna almacenará 1, ya que sólo hay una manera de obtener 0 centavos. |
| 39 | + |
| 40 | +* Para la primera iteración, tomamos una moneda que tiene un valor de 1. Entonces para todos los sub problemas, sólo hay una manera de hacer el cambio. Por 7 céntimos, la única vía es `{1,1,1,1,1,1,1}`. En la iteración final, nuestra mesa es como esta: |
| 41 | + |
| 42 | +``` |
| 43 | +[1, 1, 1, 1, 1, 1, 1, 1] |
| 44 | +``` |
| 45 | + |
| 46 | +* Para la segunda iteración, tomamos una moneda que tiene un valor de 2. A partir de aquí, todos los sub problemas que se pueden dividir por 2 almacenarán otra nueva forma de hacer un cambio. Por lo tanto, cuando la iteración se detuvo en la 2ª columna será como `dp[2] += dp[0]`. Sabemos que `dp[0]` almacenaba un valor de 1. Por lo tanto, dp[2] almacenará el valor de `1 + 1 = 2`. Desde aquí sabemos que por 2 centavos, hay 2 maneras `{1,1}` y `{2}`. Y esta operación continuará. Ahora nuestra mesa es como esta: |
| 47 | + |
| 48 | +``` |
| 49 | +[1, 1, 2, 2, 3, 3, 4, 4] |
| 50 | +``` |
| 51 | +4 maneras de ganar 7 centavos usando el valor de 1 y 2. `{{1,1,1,1,1,1,1}, {1,1,1,1,1,2}, {1,1,1,2,2}, {1,2,2,2}}` |
| 52 | + |
| 53 | +* Para la iteración final (3ª iteración), tomamos una moneda que tiene un valor de 3. Como antes, ahora todas las columnas que se pueden vided por 3 almacenarán otra nueva manera. Y el resultado final, será así: |
| 54 | + |
| 55 | +``` |
| 56 | +[1, 1, 2, 3, 4, 5, 7, 8] |
| 57 | +``` |
| 58 | + |
| 59 | +Así que la respuesta final es **8**. 8 maneras de hacer un cambio de 7 centavos usando todos los tipos de monedas. `{{1,1,1,1,1,1,1}, {1,1,1,1,1,2}, {1,1,1,2,2}, {1,2,2,2}, {1,1,1,1,3}, {1,3,3}, {2,2,3}, {1,1,2,3}}` |
| 60 | + |
| 61 | +#### Enlace de implementación de código |
| 62 | + |
| 63 | +* [Python](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/coin_change.py) |
| 64 | +* [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/coin_change.cpp) |
| 65 | +* [Java](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/CoinChange.java) |
| 66 | +* [Dart](https://github.com/TheAlgorithms/Dart/blob/master/dynamic_programming/coin_change.dart) |
| 67 | +* [Ruby](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/coin_change.rb) |
| 68 | +* [Scala](https://github.com/TheAlgorithms/Scala/blob/master/src/main/scala/DynamicProgramming/CoinChange.scala) |
| 69 | + |
| 70 | +#### Vídeo de explicación |
| 71 | + |
| 72 | +[Formas únicas totales de hacer el cambio de espaldas a espaldas SWE](https://www.youtube.com/watch?v=DJ4a7cmjZY0) |
0 commit comments