El problema de Josephus [1] es un rompecabezas matemático clásico en el que hay [matemática] n [/ matemática] personas paradas en un círculo y un verdugo mata cada [matemática] k [/ matemática] La persona viva y esto continúa hasta que solo queda una persona en el círculo. El objetivo es encontrar la posición inicial de la última persona viva.
Por ejemplo, si [matemática] n = 5 yk = 2 [/ matemática]
El orden en que las personas son asesinadas es (los números indican el número de serie de la persona asesinada al principio)
[matemáticas] 2, 4, 1, 5 [/ matemáticas]
- Cómo derribar a un sacerdote
- ¿Debería uno resolver el cubo de Rubik después de conocer el truco?
- ¿Cuáles son algunos rompecabezas lógicos clásicos?
- ¿Cuáles son algunos acertijos que tienen la respuesta en las preguntas pero que a menudo se pasan por alto?
- ¿Qué tipo de pensamiento se necesita para resolver el cubo de rubik?
la persona que vive es [matemática] 3 [/ matemática] tercera persona.
Esto se puede resolver mediante recursividad y la solución recursiva se puede mejorar mediante la programación dinámica.
Aquí hay un enfoque de complejidad [matemática] O (n) [/ matemática] para [matemática] n [/ matemática] y [matemática] k> 2 [/ matemática]
Si [matemática] n = 2 [/ matemática] entonces hay otro enfoque que es de [matemática] O (logn) [/ matemática] complejidad.
El enfoque recursivo es el siguiente:
Suponga que [matemática] f (n, k) [/ matemática] es la solución al problema y que él es el tipo afortunado que finalmente vive.
tipo con suerte (a partir de la primera iteración) = tipo con suerte (a partir de la segunda iteración)
El tipo con suerte no cambia de iteración a iteración, pero su índice de ronda a ronda cambia.
Cambiemos el sistema de indexación de [matemática] [1 a n] [/ matemática] a [matemática] [0 a n-1] [/ matemática] para simplificar la programación y la comprensión.
ahora en la primera iteración [matemática] (k-1) la persona [/ matemática] es asesinada, el número restante de personas es [matemática] n-1. [/matemáticas]
Ahora, para la segunda iteración de matar, veamos el cambio en el sistema de indexación (primera iteración [matemática] N [/ matemática] personas vivas, segunda iteración [matemática] N-1 [/ matemática] personas vivas)
primera iteración —-> [matemáticas] 0, 1, 2, 3, …, k-1, k, k + 1, …, N-2, N-1 [/ matemáticas] ( k-1ª persona asesinada)
para la segunda iteración, la indexación comienza desde [math] k. [/ math]
La quinta persona en la primera iteración será la quinta persona en la segunda iteración.
[matemática] k + 1 [/ matemática] la primera iteración de la persona estará en la 1ª posición en la segunda iteración.
de manera similar, si [math] f (n-1, k) [/ math] es la solución y el índice del tipo afortunado en la segunda iteración, entonces su índice en la primera iteración sería [math] ((k + f (n-1, k))% N) [/ matemáticas]
(el resto se toma para limitar los índices por debajo de N)
[matemática] (a% b [/ matemática] es el resto obtenido cuando [matemática] a [/ matemática] se divide por [matemática] b [/ matemática]).
Así obtenemos la relación recursiva
[matemáticas] f (n, k) = (f (n-1, k) + k)% n [/ matemáticas]
esto da la solución en 0 sistema de indexación, para obtener respuesta en 1 sistema de indexación agregue 1 a la solución.
solución recursiva:
int JosephusHelper (int n, int k)
{
if (n == 1) devuelve 0; // si solo hay una persona, su índice es 0
return ((JosephusHelper (n-1, k) + k)% n);
}
int Josefo (int n, int k)
{
devuelve 1 + JosephusHelper (n, k); // agregando 1 para cambiar la indexación
}
Solución de programación dinámica:
int Josefo (int n, int k)
{
int resultado = 0; // para n = 1
para (int i = 2; i <= n; i ++)
{
resultado = (k + resultado)% i;
}
retorno (resultado + 1); // agregando 1 para cambiar la indexación;
}
Gracias 🙂
Sharath
Notas al pie
[1] Problema de Josefo – Wikipedia