马踏棋盘算法详解

马踏棋盘算法详解

说明

  1. 马踏棋盘是指在一个8 * 8的国际棋盘上,从某一位置开始,每次走一个日字,将所有的位置都走一遍
  2. 可以使用递归 + 回溯来解决,再加上贪心算法来优化
  3. 指定某种策略,因为从棋盘的某一位置开始走,它的下一步最多有8个选择,编写一个方法,将下一步能走的位置记录在集合中
  4. 创建一个Boolean数组记录当前位置是否走过,如果没有走过则可以走,否则不能
  5. 从开始的位置开始,遍历它的下一步可以走的位置的集合,如果当前位置没有走过,则从当前位置又重新开始走,开始判断下一次可以走的位置,如果走不通则回溯
  6. 直到所有的位置都访问过,并且走完相应的步数
  7. 在从集合中选择下一步时,优先选择下一步的下一步可选择的位置较少的位置,体现贪心的思想
  8. 源码见下

源码及分析

package algorithm.algorithm.horse;

import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;

/**
 * @author AIMX_INFO
 * @version 1.0
 */
@SuppressWarnings("all")
public class HorseChessBoard {
    //棋盘的列
    public static int X;
    //棋盘的行
    public static int Y;
    //判断当前位置是否走过
    public static boolean[] visited;
    //判断是否完成
    public static boolean finished;

    public static void main(String[] args) {
        X = 8;
        Y = 8;
        int row = 2;
        int col = 4;
        visited = new boolean[X * Y];
        int[][] chessboard = new int[X][Y];

        traversalChessBoard(chessboard, row - 1, col - 1, 1);
        show(chessboard);
    }

    //显示棋盘
    public static void show(int[][] chessboard){
        for (int[] rol : chessboard) {
            for (int step : rol) {
                System.out.print(step + "\t");
            }
            System.out.println();
        }
    }

    /**
     * @param chess 棋盘
     * @param row   从棋盘的哪一行开始
     * @param col   那一列
     * @param step  表示走的第几步
     */
    public static void traversalChessBoard(int[][] chess, int row, int col, int step) {
        //设置当前位置是第几步
        chess[row][col] = step;
        //设置当前位置为已经走过
        visited[row * X + col] = true;
        //取出当前位置可以走的下一步的集合
        ArrayList<Point> ps = next(new Point(col, row));
        //使用贪心算法思想,优先走下一步选择较少的位置
        ps.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                return next(o1).size() - next(o2).size();
            }
        });
        //然后遍历下一步所有可以走的点
        while (!ps.isEmpty()) {
            Point p = ps.remove(0);
            if (!visited[p.y * X + p.x]) {
                traversalChessBoard(chess, p.y, p.x, step + 1);
            }
        }
        //当当前位置的下一个位置走不通时,判断是否走完,如果没有走完,将当前位置置为未走过
        if (step < X * Y && !finished) {
            chess[row][col] = 0;
            visited[row * X + col] = false;
        } else {
            finished = true;
        }

    }

    /**
     * \
     *
     * @param cur 当前位置点的坐标
     * @return 返回从当前位置可以走的下一个位置的所有点的集合
     */
    public static ArrayList<Point> next(Point cur) {
        //创建集合保存可以走的点
        ArrayList<Point> ps = new ArrayList<>();
        //创建一个点
        Point p = new Point();
        if ((p.x = cur.x - 2) >= 0 && (p.y = cur.y - 1) >= 0) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x - 1) >= 0 && (p.y = cur.y - 2) >= 0) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x + 2) < X && (p.y = cur.y - 1) >= 0) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x + 1) < X && (p.y = cur.y - 2) >= 0) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x + 2) < X && (p.y = cur.y + 1) < Y) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x + 1) < X && (p.y = cur.y + 2) < Y) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x - 2) >= 0 && (p.y = cur.y + 1) < Y) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x - 1) >= 0 && (p.y = cur.y + 2) < Y) {
            ps.add(new Point(p));
        }
        return ps;
    }
}

posted @ 2021-06-18 20:43  mx_info  阅读(802)  评论(0编辑  收藏  举报