¿Es posible resolver un problema de cambio de monedas para algunos elementos cíclicos a través de la programación dinámica si no se permite el uso de monedas adyacentes?

Su problema parece ser uno de esos problemas completos de NP, significa un problema de mochila.

Problema de hacer cambios

Eso fue lo primero que pensé cuando lo vi y descubrí que estaba en Wikipedia. Entonces, ¿cómo se resuelve eso?

Hay dos formas de resolver eso. El problema con esto es que se ejecuta con una necesidad exponencial de tiempo de ejecución o una necesidad exponencial de memoria. En pequeñas cantidades de piezas se puede resolver por fuerza bruta, pruebe todos los casos. Después de eso solo tienes heurística.

La heurística le dará una solución, pero no se garantiza que sea la mejor. Por lo general, hay varias formas de escalar colinas para hacer eso. O simplemente comienzas con las monedas grandes y subes la colina probando las más pequeñas. Esa sería una forma simple de reducir el problema suponiendo que es la mejor manera de acercarse a la solución y luego ver qué tan lejos llega.

Puede hacerlo con un algoritmo de búsqueda A * modificado, por ejemplo. Hay algunos otros, pero ese sería mi primer intento, supongo.

Pero por lo general, adoptará un enfoque de Monte Carlo como un algoritmo evolutivo. Puede usar la Biblioteca de Utilidad de Algoritmo Genético para eso en C para soluciones reales o el DEAP (software) en Python para crear prototipos de su problema.

Ese sería el enfoque más fácil, supongo.

El problema con los algoritmos evolutivos es que es uno que siempre está funcionando, pero con frecuencia no es el más eficiente. Encontrar una buena heurística es el elemento clave de su problema, si desea optimizarlo. Aún así, el algoritmo evolutivo encontrará una buena solución en muy poco tiempo.

Y si quieres llegar a una solución más rápida, prueba el A *. Su heurística será la estimación de cuán buena es la solución que encontró. Para A * siempre tiene que estimar si su próximo paso lo ha acercado a su meta o no. Y ese es el punto de sus conjeturas, de sus heurísticas.

Funcionará más rápido, supongo. Los algoritmos evolutivos son geniales, a menudo son un poco vagos, lo que significa que las personas no pensaron el problema lo suficiente. Es Monte Carlo y simplemente arrojas el algoritmo a todo lo que se te presenta y esperas una respuesta mágica. Pero esa no será la forma más eficiente.

Es más fácil de resolver si no considera que el primer y el último elemento sean consecutivos. El programa dinámico simple tiene una matriz bidimensional donde A [n, k] es el número mínimo de monedas necesarias para alcanzar el valor exactamente k usando las primeras n monedas. Tenga en cuenta que A [n, k] podría ser infinito si no hay forma de hacer cambios para k con las primeras n monedas.

Ahora, para encontrar A [n, k] consideramos cuántas de la enésima moneda toma. Diremos que el valor de la enésima moneda es un (n) para evitar preocuparse por problemas ocasionales. Si no toma ninguna de las monedas n-ésima, solo necesita hacer el cambio lo mejor que pueda con las primeras monedas n-1, así que busque A [n-1, k]. Si usa c de la enésima moneda, está restringido a usar las primeras n-2 monedas, por lo que debe buscar A [n-2, k-ca (n)] y agregar c al valor para encontrar el Número mínimo de monedas totales necesarias para este caso. Haga esto para cada valor de c donde k hasta k / a (n). A [n, k] es el mínimo de todos los valores A [n-1, k] y A [n-2, k-ca (n)] + c que ha calculado aquí.

Ahora puede resolver el problema con la programación dinámica, excepto que puede terminar usando la primera y la última moneda. Para solucionar este problema, puede agregar otra dimensión a su tabla para indicar si se usa la primera moneda y hacer que su código verifique que durante la última fase de la moneda o puede ejecutar su algoritmo dos veces, una con la primera moneda eliminada y otra con la última moneda eliminada para asegurarse de que no se usen ambos.