ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

骑士周游问题

2021-11-21 16:33:34  阅读:200  来源: 互联网

标签:ps 周游 p1 Point int 问题 curPoint new 骑士


算法

1. 骑士周游问题

  1. 马踏棋盘算法也被称为骑士周游问题

  2. 将马随机放在国际象棋的 8x8 棋盘中[0~7][0~7]的某个方格中,马鞍走起规则(马走日字)进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格

    image-20211121140959076

​ 3. 会使用到图的遍历算法(DFS)+ 贪心算法优化

1.1 普通方法

package com.example.mhl_demo.day01;

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

/**
 * 骑士周游
 */
public class HouseChessBoard {
    //定义属性
    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 = 5;
        int col = 5;
        //测试
        long start = System.currentTimeMillis();
        traversalChessBoard(chessBoard,row-1,col - 1,1);
        long end = System.currentTimeMillis();
        System.out.println("运行时间:" + (end - start) + "ms");

        //输出当前棋盘的情况
        for (int[] rows : chessBoard) {
            for (int step : rows) {
                System.out.print(step + "\t");
            }
            System.out.println();
        }

    }

    /*
        编写最核心的算法,遍历棋盘,入股遍历成功,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));
        //遍历
        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;
        }
    }


    //编写方法,可以获取当前位置的下一步的所有位置
    public static ArrayList<Point> next(Point curPoint) {
        //创建一个ArrayList
        ArrayList<Point> ps = new ArrayList<>();

        //创建一个point(点),准备放入ps
        Point p1 = new Point();

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

1.2 贪心算法优化

使用贪心算法,进行优化,提高速度

分析

  • 我们现在走的位置,是按照我们的顺时针来挑选位置,因此选择的这个点的下一个可以走的位置的个数是不确定。
  • 优化思路:我们应该选择下一个点的下一个点可以走的位置较少的点,开始走,这样可以减少回溯的次数
    • 代码:对我们的 ps 集合 按照可以走的下一个位置的次数进行排序,升序排序。
/*
    编写一个方法,对ps的各个位置,可以走的下一个位置的次数进行排序,
    按照从小到大的顺序进行排序
 */
public static void sort(ArrayList<Point> ps){
    ps.sort((o1, o2) -> next(o1).size() - next(o2).size());
}

traversalChessBoard中获取next方法之后 进行排序

/*
    编写最核心的算法,遍历棋盘,入股遍历成功,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));
    //排序
    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);
        }
    }
}

标签:ps,周游,p1,Point,int,问题,curPoint,new,骑士
来源: https://blog.csdn.net/weixin_42553198/article/details/121455544

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有