N reinas, X por Y Junta decisión problema entrevista pregunta

10

Me hicieron la siguiente pregunta en una entrevista hoy y he estado pensando en eso desde entonces. No pude responderlo y no pude encontrar una solución en línea.

Dado un tablero de ajedrez con dimensiones X por Y y N reinas, determine si es posible organizar estas reinas en el tablero de modo que no puedan atacarse entre sí.

Una placa de 2 x 3 con 2 reinas tiene una solución, por lo que el algoritmo devolvería verdadero:

Q . .
. . Q

Estoy buscando un enfoque de programación para este rompecabezas, no solo formas de resolverlo en papel, por ejemplo.

Entrevistado
fuente
Best First Search es sin duda una opción, al igual que otras heurísticas de búsqueda
Jason
2
nominado para una de las peores preguntas de la entrevista, a menos que el software en el que trabajan se base en soluciones de retroceso, en cuyo caso es totalmente relevante
Steven A. Lowe
1
Para ser justos, el entrevistador dijo que esto era simplemente un tipo de crédito adicional. El resto de la entrevista fue bastante legítima OMI. Solo tenía curiosidad.
Entrevistado el
Tal vez fue una prueba si haría una simulación con retroceso o (piense en encontrar) la solución O (1) utilizando los hechos declarados por Caleb en su respuesta. La capacidad de programar cosas simples no es todo lo que uno necesita en el trabajo.
Sopel
las tareas están explícitamente fuera de alcance aquí.
Jwenting

Respuestas:

16

Este no es (IMO) un problema muy interesante desde el punto de vista de la programación. Podría llegar a un algoritmo recursivo que intente cada arreglo, algo como esto:

bool try_queens(Board board, int n)
{
    if (n == 0) {
        // no queens left to place, so we're done
        return true
    }
    // try each open position until we find one that works
    for each position on the board {
        if (is_empty(board, position) and not is_attacked(board, position)) {
            place_queen(board, position)
            if (try_queens(board, n-1)) {
                return true
            }
            remove_queen(board, position)
        }
    }
    // if we get this far, there's no available position
    return false
}

main()
{
    initialize board(X,Y)
    return try_queens(board, N)
}

Si piensas un poco en el problema, te darás cuenta de que no hay forma de colocar N reinas en un tablero donde X <N o Y <N porque eso requeriría que al menos dos reinas terminen en el mismo rango o archivo, y por lo tanto se atacarían entre sí. Si lees sobre el problema de las n reinas, aprenderás rápidamente que siempre es posible colocar N reinas en un tablero NxN para N> 3. Ahora sabemos que la respuesta es NO para (X <N o Y <N) y SÍ para (X> = N e Y> = N, N> 3). Todo lo que queda son los casos especiales:

  • N = 1 (SÍ)
  • N = 2 (SÍ para X> = 2 e Y> 2 o viceversa)
  • N = 3 (SÍ para X> = 3 e Y> 3 o viceversa)

Entonces, nuestra agradable función recursiva se convierte en una función simple que solo compara N con X e Y y devuelve un resultado fijo. Eso es excelente desde el punto de vista del rendimiento, ya que puede obtener una respuesta en tiempo constante. No es tan bueno desde el punto de vista de la programación porque te das cuenta, en este punto, que la pregunta es realmente más sobre qué tan bien puedes resolver acertijos que sobre tu habilidad para escribir una función recursiva.

(Y chico, chico, realmente espero no haber cometido un error tonto en mi respuesta de smarty-pants. ;-)

Caleb
fuente
That's great from a performance point of view, since you can get an answer in constant time. It's not so great from a programming point of view because you realize, at this point, that the question is really more about how well you can solve puzzles than it is about your ability to write a recursive function.De hecho, creo que el entrevistador estaba esperando esa solución O (1) porque en última instancia es mejor y no es obvio para muchas personas. El problema de nxn queen está en todos los cursos de programación como un ejercicio de recursión: muchas personas no pensarán más profundamente al ver ese problema nuevamente.
Sopel
4

Si el entrevistador le ha pedido que escriba el código del problema, creo que no es justo. El algoritmo requiere trabajo. Sin embargo, si la idea era mostrarle al entrevistador las clases, los métodos o algunos conceptos que necesitaría usar o algo similar, entonces puede ser una pregunta justa.

El problema es un problema clásico de informática y se discute en muchos de esos libros. Aquí se puede encontrar una excelente explicación, con animación y 12 soluciones diferentes junto con algo de código:

http://en.wikipedia.org/wiki/Eight_queens_puzzle

También se puede encontrar el código aquí: http://www.codeproject.com/KB/java/EightQueen.aspx

No se sienta mal por esto, como dije, no es fácil.

Ninguna posibilidad
fuente
0

Esto es más un comentario realmente, pero no encaja allí ...

Un tablero de ajedrez tiene 8x8 cuadrados, ni más ni menos (estas preguntas siempre me molestan con ese enfoque de un tablero de ajedrez personalizado).

Pero de todos modos, si tienes un tablero de ajedrez x * y, y n reinas y tomando eso, la reina "toma" estos campos

ingrese la descripción de la imagen aquí

¿podría crear una matriz bidimensional y "marcar" todos los campos que ataca una reina? Luego coloque el otro (desde el centro del tablero), marque los campos restantes, y así sucesivamente ... hasta que ejecute cualquiera de los campos o reinas.

Este es, por supuesto, un enfoque muy simplificado, ya que si se coloca de una manera mala, creo que el número máximo de reinas variaría.

Hmm, acabo de encontrar esto también - problema de 8 reinas.

Torre
fuente
Al principio propuse este algoritmo exacto, pero tenga en cuenta que no está garantizado que si adopta este enfoque y termina sin lugares para colocar a su última Reina que realmente ha determinado que es imposible. Solo has eliminado ese arreglo en particular. Esto es básicamente una aplicación de la heurística del vecino más cercano.
Entrevistado el
@Interviewee - Sí, lo sé. Esto es algo que pensé en la parte superior de mi cabeza. Como se dijo, es un problema interesante y probablemente podría mejorarse, pero a las 4 a.m. (aquí) soy demasiado vago para pensar. Por cierto, ¿cómo fue la entrevista?
Rook
@Interviewee, esta es la idea correcta. La parte que falta es que si descubres que no hay lugar para la última reina, retrocedes e intentas una posición diferente para la penúltima reina. Si no hay lugar para esa reina que permita la colocación de la última reina, retrocede otro nivel e intenta un lugar diferente para la tercera a la última reina, y así sucesivamente.
Caleb
Me gusta que tu avatar sea una pieza de ajedrez :)
warren
0

Básicamente, el algoritmo de retroceso funciona así:

  1. Crea una matriz X por Y. Establecer todos los cuadrados para vaciar.

  2. Establecer el recuento de la reina a cero.

  3. Establezca su posición actual en (1,1)

  4. Vea si puede colocar una reina en la posición actual.

  5. Si puede, configure la matriz (X, Y) en reina, incremente el recuento de reina. Si colocaste toda la reina, detente , tienes una solución.

  6. Si la posición actual no es (X, Y), incremente la posición actual y vaya al paso 4.

  7. Encuentra a la reina en la última posición (la que viene última en el orden en que incrementas las posiciones). Establece la posición actual en la posición de esa reina, quítala y disminuye el recuento de reina.

  8. Si el recuento de la reina es cero, deténgase , no hay solución.

  9. Incrementar la posición actual.

  10. Ve al paso 4.

David Schwartz
fuente
En esta descripción, el algoritmo no retrocede correctamente: solo elimina la última reina colocable; corre el riesgo de nunca intentar reinas anteriores en otras posiciones.
Kasper van den Berg
@KaspervandenBerg El algoritmo retrocede correctamente. Yo respondería directamente a tu crítica, pero honestamente no puedo entenderla. No sé a qué te refieres con "última reina colocable". Solo eliminará a la última reina colocada, pero cualquier reina puede convertirse en la última reina colocada una vez que las reinas se colocan después de que se haya eliminado. Retrocederá tanto como sea necesario, eliminando reinas en el reverso del orden en que se colocaron.
David Schwartz
0

Agregando a las otras respuestas: crear una matriz bidimensional solo complica el código.

Solo necesita un vector de tamaño 8 para un tablero de ajedrez normal. O 8 + 1 si, como C, la primera posición es 0, solo para simplificar el código, y tratar con 1-8 y no con 0-7.

Si piensa que x es su posición en la matriz, yy es el contenido de la posición. Por ejemplo, el tablero [1] = 8 significa que la primera reina está en [1,8].

De esa manera, solo necesita verificar la validación de las columnas.

En la facultad, me encontré con un libro muy antiguo (¿60?), Sobre algoritmos implementados en Dartmouth BASIC, que implementaba el problema de las 8 reinas usando la menor memoria posible (siendo tan viejo, tiene sentido).

Hasta donde recuerdo, usó la idea del vector, y esencialmente bruto forzó todas las posiciones en el tablero con dos ciclos FOR. Para verificar la validez de la posición, usó un tercer ciclo, un ciclo MIENTRAS en cada posición retrocede en el vector, y busca un número igual, o una fórmula que usa una operación tangente para verificar las diagonales.

Lamentablemente, perdí el rastro de ese libro ...

Dicho algoritmo encontró todas las soluciones para el problema de n-queen.

Rui F Ribeiro
fuente
0

Si solo tiene que escribir un algoritmo para determinar si existe tal disposición, mire la investigación existente:
El rompecabezas de las ocho reinas en Wikipedia .

Puede devolver trivialmente falso si N> min (X, Y).
Después de leer esa página, sabe que devuelve verdadero si N <= min (X, Y) y 2, 3! = Min (X, Y).

Lo que deja 2, 3 == min (X, Y) y N <= min (X, Y).

Bueno, si N <min (X, Y), encontrar una solución es trivial.
Si N == min (X, Y), solo hay una solución si max (X, Y)> N.

f(X, Y, N)
    if X < Y => f(Y, X, N)
    if Y > N => false
    => (Y < N) or (Y != 2 and Y != 3) or (X > N)
Deduplicador
fuente
0

Obviamente no hay solución si N> min (X, Y). De lo contrario, puede mostrar fácilmente que no hay solución para N = X = Y = 2, N = X = Y = 3. Para todos los demás casos, parece haber una solución. El número de soluciones parece aumentar a medida que N crece.

Puede encontrar una solución a través de una búsqueda exhaustiva con retroceso: ponga una reina en la primera fila, columna 1. Coloque una reina en la segunda fila, en la primera columna que la reina en la fila 1 no puede alcanzar. Pon una reina en la segunda fila, etc. Si una reina no se puede poner en la fila k, entonces la quitas y mueves a la reina en la fila k-1 a la siguiente posición desocupada.

gnasher729
fuente