十大常用算法-马踏棋盘算法(使用贪心算法优化)--优化细节:对节点的next集合的元素的next集合个数进行非递减排序,也就是可以有重复数据的递减,重新达到比较小次数的回溯,就像之前的集合匹配从大到小

public class HorseChessBox {

    //static 常量棋盘行数
    static  int x=8;
    //常量棋盘列数
    static  int y=8;
    //用来遍历输出比较次数
    static int count = 0;
    // 创建一个数组 标记各个位置是否被访问过
    private static boolean[] visited;
    // 使用一个属性 标记棋盘的所有位置是否被 访问过
    private static boolean finished;

    public static void main(String[] args) {
        int row = 2; // 马儿初始位置的行
        int clo = 4; // 马儿初始位置的列
        //定义棋盘
        int [][] chessboard = new int[x][y];
        //初始访问数组都是false
        visited = new boolean[x * y];
        // 测试一下花费时间
        long start = System.currentTimeMillis();
        System.out.println("开始时间 " + start);
        traversalChessBoard(chessboard, row - 1, clo - 1, 1);
        long end = System.currentTimeMillis();
        System.out.println("结束时间 " + end);
        System.out.println("功共耗时 " + (end - start) + "毫秒");
        System.out.println("输出结果");
        for (int[] arr : chessboard) {
            System.out.println(Arrays.toString(arr));
        }
    }

    /**
     * 完成马踏棋盘算法
     * @param chessboard 棋盘
     * @param row 马儿当前位置的行
     * @param col 马儿当前位置的列
     * @param step 表示马儿走的是第几步 初始位置是第一步
     */
    public static void traversalChessBoard(int[][] chessboard, int row, int col, int step) {
        System.out.println("第" + (++count) + "次比较");
        //先把第一步定义在棋盘上
        chessboard[row][col] = step;
        // 若第四行 row=4  x为 8 clo = 4  4 * 8  = 4 = 36  (从1开始 所以 37 -1 = 36) 看图!!!
        visited[row * x + col] = true; // 标记已访问
        // 获取下一节点的位置的集合
        ArrayList<Point> ps = next(new Point(col, row));
        //在进行遍历之前,先对next数组进行贪心算法的优化
        sort(ps);
        //使用while循环判断是否为空,因为每次循环进去都需要从arraylist中remove出一个节点来进行判断
        while (!ps.isEmpty()) {
            //remove第一个节点
            Point p = ps.remove(0);
            //判断节点时候已经被访问,如果没有被访问过,则进行遍历
                if (!visited[p.y * x + p.x]) {
                    // 没有访问过
                    traversalChessBoard(chessboard, p.y, p.x, step + 1);
                }
        }
        //这里就是路走不通的时候进行回溯,这里的回溯其实是在内层循环时的回溯
        //也就是比如当我找第一个节点的时候,回递归进入下一个节点找它的下一个节点,如果下一个节点的下一个节点集合都已经被访问或者是不存在,则进行回溯,回到第一个点找下一个节点的时候,去找另一个下节点
            if (step < x * y && !finished) {
            chessboard[row][col] = 0;
            visited[row * x + col] = false;
        }else {
            finished = true;//如果全部都已经被访问了,则将finished设true
        }
    }

//判断当前节点下次可以走的节点的集合
    public static ArrayList<Point> next(Point curPoint){
        // 创建一个ArrayList
        ArrayList<Point> ps = new ArrayList<>();
        /// 创建一个point对象
        Point p1 = new Point();
        //走图中5的位置
        if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) {
            ps.add(new Point(p1));
        }
        //图中6的方向
        if ((p1.x=curPoint.x-1)>=0 &&(p1.y=curPoint.y-2)>=0){
            ps.add(new Point(p1));
        }
        // 判断可不可以走可以走 图中'7'的位置
        if ((p1.x = curPoint.x + 1) < x && (p1.y = curPoint.y - 2) >=0) {
            ps.add(new Point(p1));
        }
        // 判断可不可以走可以走 图中'0'的位置
        if ((p1.x = curPoint.x + 2) < x && (p1.y = curPoint.y - 1) >=0) {
            ps.add(new Point(p1));
        }
        // 判断可不可以走可以走 图中'1'的位置
        if ((p1.x = curPoint.x + 2) < x && (p1.y = curPoint.y + 1) < y) {
            ps.add(new Point(p1));
        }
        // 判断可不可以走可以走 图中'2'的位置
        if ((p1.x = curPoint.x + 1) < x && (p1.y = curPoint.y + 2) < y) {
            ps.add(new Point(p1));
        }
        // 判断可不可以走可以走 图中'3'的位置
        if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < y) {
            ps.add(new Point(p1));
        }
        // 判断可不可以走可以走 图中'4'的位置
        if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < y) {
            ps.add(new Point(p1));
        }
        return ps;
    }


    //使用贪心算法优化马踏棋盘
    public static void sort(ArrayList<Point> ps){
        ps.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                //前者比较小,则返回负数
                if (next(o1).size()<next(o2).size()){
                    return -1;
                    //前者比较大则返回正数
                } else if (next(o1).size()>next(o2).size()){
                    return 1;
                    //两个一样大,则返回0
                } else {
                    return 0;
                }
            }
        });
    }
}

  优化后效率: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值