El análisis de problemas más conciso y el resumen de rutina de las ocho reinas de la historia.

Dirección del proyecto github: bitcarmanlee, algoritmo fácil, entrevista y práctica, da la
bienvenida a todos a protagonizar, dejar un mensaje y aprender y progresar juntos

1. ¿Cuál es el problema de las ocho reinas?

El problema de las ocho reinas es un problema basado en el ajedrez: ¿cómo se pueden colocar ocho reinas en un tablero de ajedrez de 8 × 8 para que ninguna reina pueda capturar directamente a las otras reinas? Para lograr este objetivo, no pueden haber dos reinas en la misma línea horizontal, vertical o diagonal. El problema de las ocho reinas se puede generalizar al problema más general de colocación de n reinas: el tamaño del tablero de ajedrez se convierte en n × n, y el número de reinas también se convierte en n. El problema puede resolverse si y solo si n = 1 o n ≥ 4. (La descripción del problema es de la referencia 1)

Inserte la descripción de la imagen aquí

El príncipe de las matemáticas Gauss dedicó innumerables esfuerzos ese año y finalmente calculó que hay 76 soluciones para el problema de las ocho reinas. Ahora podemos calcular fácilmente las verdaderas soluciones al problema de las ocho reinas a través de simulaciones por computadora. Uno puede imaginar la complejidad y dificultad de los cálculos que pueden hacer tropezar a Gauss.

2. Análisis de la solución

Gauss deriva 76 soluciones de las ocho reinas, que ya es muy poderosa. Esto no puede culpar a Gauss, pero la complejidad computacional de las Ocho Reinas es realmente demasiado alta.
La idea general del problema sigue siendo una solución violenta
: 1. Primero enumere todos los posibles métodos de colocación de reinas.
2. Compruebe si el método de colocación cumple los requisitos.

El proceso de implementación específico es el siguiente:
primero coloque la primera reina en la primera fila y primera columna, y luego coloque la segunda reina en la segunda fila y primera columna, para determinar si el arreglo cumple con los requisitos. Obviamente esto no funcionará, habrá dos reinas en la misma columna. Ponga la segunda reina en la segunda fila y segunda columna. Esto no funcionará. Las dos reinas estarán en una línea diagonal. Coloque la segunda reina en la segunda fila y tercera columna para que se cumplan las condiciones actuales.
Ya hay dos reinas que cumplen las condiciones, para luego poner la tercera, o empezar desde la primera columna de la tercera fila, y poner la segunda columna si no se cumple la condición, la tercera columna ... hasta la octava reina También se puede colocar En una posición no conflictiva, encuentre una solución que cumpla con los requisitos en este momento.
Luego comenzamos a retroceder y colocamos la primera reina en la primera fila y la segunda columna, y esta última continuará girando de la manera anterior hasta que se complete el retroceso y se encuentren todas las soluciones que cumplan con las condiciones.

La referencia 2 tiene una imagen que describe el proceso anterior con más detalle y la publica para su referencia. La siguiente figura describe el proceso de retroceso de las 4 reinas, y el principio es el mismo que el de las 8 reinas.
Inserte la descripción de la imagen aquí

3. Implementación del código

Una vez completado el análisis del principio anterior, veamos la implementación del código.

public class NQueueV2 {

    public static int N = 4;
    public static int[][] boards = new int[N][N];

    public static int result = 0;

    public static void putQueQue(int k) {
        if (k == N) {
            result++;
            for(int row=0; row<N; row++) {
                for(int col=0; col<N; col++) {
                    System.out.print(boards[row][col] + " ");
                }
                System.out.println();
            }
            System.out.println();
        } else {
            for(int i=0; i<N; i++) {
                if (check(k, i)) {
                    boards[k][i] = 1;
                    putQueQue(k+1);
                    boards[k][i] = 0;
                }
            }
        }
    }

    public static boolean check(int row, int column) {
        for(int i=0; i<row; i++) {
            if (boards[i][column] == 1) {
                return false;
            }
        }

        for(int m=row-1, n=column-1; m>=0 && n >= 0; m--, n--) {
            if (boards[m][n] == 1) {
                return false;
            }
        }

        for(int m=row-1, n=column+1; m>=0 && n<N; m--, n++) {
            if (boards[m][n] == 1) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        putQueQue(0);
        System.out.println("result is: " + result);
    }
}

Resultado de salida de código:

0 1 0 0 
0 0 0 1 
1 0 0 0 
0 0 1 0 

0 0 1 0 
1 0 0 0 
0 0 0 1 
0 1 0 0 

result is: 2

El código anterior, para facilitar la salida del resultado final, simula 4 reinas, y 8 reinas solo necesitan cambiar N a 8.

Una matriz bidimensional de tablero, que simula un tablero de ajedrez, y el estado inicial es 0, lo que significa que no se coloca ninguna reina en esta posición. Si la posición se establece en 1, significa que hay una reina en la posición.

k representa el número de reinas colocadas. Si k == N, significa que se han colocado todas las N reinas y se obtiene una solución válida en este momento.

            for(int row=0; row<N; row++) {
                for(int col=0; col<N; col++) {
                    System.out.print(boards[row][col] + " ");
                }
                System.out.println();
            }

Esta parte del código da como resultado el estado de una solución válida. La posición de 1 en la matriz indica que la reina está colocada en esa posición.

En otra parte del código, i representa la i-ésima columna, y el método check (k, i) representa si es legal colocar la reina en la posición (k, i)

        for(int i=0; i<row; i++) {
            if (boards[i][column] == 1) {
                return false;
            }
        }

Esta parte del código significa que no se pueden colocar dos reinas en la misma columna.

        for(int m=row-1, n=column-1; m>=0 && n >= 0; m--, n--) {
            if (boards[m][n] == 1) {
                return false;
            }
        }

Esta parte del código significa que la barra izquierda de la reina no puede tener reina.

        for(int m=row-1, n=column+1; m>=0 && n<N; m--, n++) {
            if (boards[m][n] == 1) {
                return false;
            }
        }

Esta parte del código significa que la parte de barra derecha de la reina no puede tener reina.

Si la reina puede colocarse en esta posición, establezca la posición en el tablero de ajedrez en 1, y luego coloque la reina putQueQue (k + 1) en la siguiente línea. Al mismo tiempo, al retroceder, la posición debe establecerse en 0.

4. Resumen de rutina

Entonces, el problema aparentemente complicado de las ocho reinas, mirar el diagrama y luego mirar el análisis del código, ¿no se siente tan difícil?
La esencia es el uso de algoritmos de retroceso clásicos, similares a las permutaciones y combinaciones que mencionamos anteriormente. Después de comprender todo el proceso, la dificultad de retroceder es incluso menor que la de la permutación y la combinación.
En un artículo se ofrece una explicación detallada del algoritmo de combinación y permutación más completo de la historia y un resumen de las rutinas.

referencias

1.https: //zh.wikipedia.org/wiki/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98
2.https: // juejin.cn/post/6844903798926753805

Supongo que te gusta

Origin blog.csdn.net/bitcarmanlee/article/details/114548541
Recomendado
Clasificación