El problema y la optimización del roaming de caballeros

Los artículos y códigos se han archivado en [Github warehouse: https://github.com/timerring/java-tutorial ] o la cuenta pública [AIShareLab] también se puede obtener respondiendo a java .

problema de la gira del caballero

Importancia de la optimización del algoritmo


  1. Los algoritmos son el alma de los programas ¿Por qué algunos programas aún pueden mantener cálculos de alta velocidad cuando calculan cantidades masivas de datos ?

  2. Hay muchos algoritmos en la programación, como ocho algoritmos de clasificación (burbuja, selección, inserción, clasificación rápida, combinación.
    Hill, radix, clasificación de montón), algoritmo de búsqueda, algoritmo de división y conquista, algoritmo de programación dinámica, algoritmo KMP, algoritmo codicioso, Algoritmo de Puri Mu, algoritmo de Kruskal, algoritmo de Dijkstra, algoritmo de Floyd.

Preguntas de entrevista de algoritmo clásico: problema de viaje de los caballeros

Introducción al algoritmo de tablero de ajedrez paso a paso

  1. El algoritmo de tablero de ajedrez de paso de caballo también se conoce como el problema de la gira del caballo.
  2. El caballo se coloca aleatoriamente en un cuadrado determinado en el tablero de ajedrez de 8 × 8 Board[0 ~7][0~7], y el caballo se mueve de acuerdo con las reglas del ajedrez (caracteres japoneses que caminan a caballo). Se requiere ingresar a cada casilla solo una vez y caminar por las 64 casillas del tablero.
  3. Demostración del juego:
    https://u.ali213.net/games/horsesun/index.html?game_code=403
  4. Utilizará algoritmo de recorrido de gráfico (DFS) + optimización de algoritmo codicioso

  1. El problema del tablero de ajedrez a paso de caballo (problema del recorrido del caballo) es en realidad una aplicación de búsqueda en profundidad (DFS) en gráficos.
  2. Si usa el retroceso (es decir, la búsqueda primero en profundidad) para resolverlo, si el caballo pisó 53 puntos, como se muestra en la figura: llegó al punto 53, coordenadas (1,0), y encontró que tiene llegado al final, no hay manera, entonces solo puede retroceder, verificar otras rutas y seguir retrocediendo en el tablero de ajedrez ..., pensando en el análisis + implementación del código.
  3. Primero use el método básico para resolverlo y luego use el algoritmo codicioso (algoritmo codicioso) para optimizar. Resuelva el problema del caballo que pisa el tablero de ajedrez y experimente el impacto de diferentes algoritmos en la eficiencia del programa.
  4. Utiliza el juego anterior para comprobar que el algoritmo es correcto.

Análisis de los pasos e ideas para resolver el problema de los caballeros que viajan

  1. Crea un tablero de ajedrez chessBoard, que es una matriz bidimensional
  2. Establezca la posición actual como ya visitada, y luego calcule a qué posiciones puede ir el caballo de acuerdo con la posición actual, y colóquelas en una colección (ArrayList), con un máximo de 8, y use el paso + 1 para cada paso.
  3. Recorra todas las ubicaciones almacenadas en ArrayList para ver cuál puede pasar, si puede pasar, continuar, si no pasa, retroceder.
  4. Para juzgar si el caballo ha completado la tarea, use el paso para comparar con la cantidad de pasos que se deben dar. Si no se alcanza el número, significa que la tarea no se ha completado y todo el tablero de ajedrez se establece en 0.

Nota: La estrategia de caminar a caballo es diferente, y el resultado y la eficiencia también son diferentes.

Utilice el algoritmo codicioso en el código para optimizar y mejorar la velocidad:

analizar

  1. La siguiente posición a la que vamos ahora es seleccionar la posición de acuerdo con nuestra dirección en el sentido de las agujas del reloj, por lo que el número de la siguiente posición que se puede mover en este punto seleccionado es incierto.
  2. La idea de optimización es: debemos elegir el siguiente punto donde haya menos lugares a los que podamos ir y comenzar a caminar, lo que puede reducir el retroceso.
  3. Código: Ordene nuestra colección ps de acuerdo con la cantidad de veces que se puede tomar la siguiente posición, en orden ascendente.
package com.hspedu;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;
public class HorseChessBoard {
    
    

    //定义属性
    private static int X = 6; // 表示col
    private static int Y = 6; // 表示row
    private static int[][] chessBoard = new int[Y][X]; //棋盘
    private static boolean[] visited = new boolean[X * Y];//记录某个位置是否走过
    private static boolean finished = false; //记录马儿是否遍历完棋盘.

    public static void main(String[] args) {
    
    

        int row = 2;
        int col = 2;

        //测试一把
        long start = System.currentTimeMillis();
        traversalChessBoard(chessBoard, row - 1, col - 1, 1);
        long end = System.currentTimeMillis();

        System.out.println("遍历耗时=" + (end - start));
        //输出当前这个棋盘的情况
        for (int[] rows : chessBoard) {
    
    
            for (int step : rows) {
    
    //step 表示 该位置是马儿应该走的第几步
                System.out.print(step + "\t");
            }
            System.out.println();
        }
    }

    //写一个方法,对ps的各个位置,可以走的下一个位置的次数进行排序, 把可能走的下一个位置从小到大排序
    public static void sort(ArrayList<Point> ps) {
    
    
        ps.sort(new Comparator<Point>() {
    
    
            @Override
            public int compare(Point o1, Point o2) {
    
    
                return next(o1).size() - next(o2).size();
            }
        });
    }

    //编写最核心的算法,遍历棋盘,如果遍历成功,就把 finished 设置为true ,
    //并且,将马儿走的每一步step,记录到 chessBoard
    public static void traversalChessBoard(int[][] chessBoard, int row, int col, int step) {
    
    

        //先把step 记录到 chessBoard
        chessBoard[row][col] = step;
        //把这个位置,设置为已经访问
        visited[row * X + col] = true;
        //获取当前这个位置可以走的下一个位置有哪些
        ArrayList<Point> ps = next(new Point(col, row)); // 注意这里的处理: col - X , row - Y
        sort(ps);// 排序:我们应该选择下一个的下一个可以走的位置较少的点,开始走,这样可以减少回溯
        //遍历
        while (!ps.isEmpty()) {
    
    
            //取出当前这个 ps 第一个位置(点)
            Point p = ps.remove(0);
            //判断该位置是否走过,如果没有走过,我们就递归遍历
            if (!visited[p.y * X + p.x]) {
    
    
                //递归遍历
                traversalChessBoard(chessBoard, p.y, p.x, step + 1);
            }
        }

        //当退出while,看看是否遍历成功, 如果没有成功,就重置相应的值,然后进行回溯
        if (step < X * Y && !finished) {
    
    
            //重置
            chessBoard[row][col] = 0;
            visited[row * X + col] = false;
        } else {
    
    
            finished = true;
        }

    }

    //编写方法,可以获取当前位置,可以走的下一步的所有位置(Point表示 x,y)
    public static ArrayList<Point> next(Point curPoint) {
    
    

        //创建一个ArrayList
        ArrayList<Point> ps = new ArrayList<>();

        //创建一个Point对象(点/位置), 准备放入到 ps
        Point p1 = new Point();

        //判断在 curPoint 是否可以走如下位置,如果可以走,就将该点(Point) 放入到ps

        //判断是否可以走5位置
        if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) {
    
    
            ps.add(new Point(p1)); //这里一定要new Point
        }
        //判断是否可以走6位置
        if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y - 2) >= 0) {
    
    
            ps.add(new Point(p1)); //这里一定要new Point
        }
        //判断是否可以走7位置
        if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0) {
    
    
            ps.add(new Point(p1)); //这里一定要new Point
        }
        //判断是否可以走0位置
        if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0) {
    
    
            ps.add(new Point(p1)); //这里一定要new Point
        }
        //判断是否可以走1位置
        if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y) {
    
    
            ps.add(new Point(p1)); //这里一定要new Point
        }
        //判断是否可以走2位置
        if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y) {
    
    
            ps.add(new Point(p1)); //这里一定要new Point
        }
        //判断是否可以走3位置
        if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y) {
    
    
            ps.add(new Point(p1)); //这里一定要new Point
        }
        //判断是否可以走4位置
        if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < Y) {
    
    
            ps.add(new Point(p1)); //这里一定要new Point
        }
        return ps;
    }
}

Supongo que te gusta

Origin blog.csdn.net/m0_52316372/article/details/131412596
Recomendado
Clasificación