马踏棋盘算法(骑士周游问题)java算法实现贪心策略优化源代码

9 篇文章 0 订阅
7 篇文章 0 订阅

马踏棋盘{骑士周游问题解决步骤&思路}_汉密尔顿通路问题
比如6*6的网格中
要符合规则踏遍36个格子
1.这是一个DFS问题,需要回溯

1.把棋盘创建8*8 chessBoard 是一个二维数组
2.将当前这个位置设置为已经访问,根据当前位置,计算马还能走那些位置,并放入集合中lsit—count++
3.遍历list中存放的所有位置,看看那个可以走通
4.判断马儿是否完成任务 用计数器,走一步count++ if step和该走的步数比较,没达到失败,整个棋盘置0

这种方法,没有优化,可以用贪心算法进行优化{策略}
思路:使用贪心算法对原来的短发进行优化
:需要对ps中的所有的下一步的所有集合的数目进行非递减排序,{优先选择集合中选择更少的点进行回溯,进行找到第一个解法}

递减: 9 7 6 5 3 2 1
非递减: 1 2 2 2 3 3 4 5 6 //可以有重复的值
重写sort方法
采用不同的策略,得到的解不一样
在这里插入图片描述

public class HorseChessBoard {
    private static int X; //棋盘的列
    private static int Y; //棋盘的行
    //创建一个数组,标记棋盘的各个位置是否被访问过
    private static boolean visited[]; //访问标记
    //使用一个属性标记所有位置被访问
    private static boolean finished;//如果true,表示成功   默认为false


    public static void main(String[] args) {
        System.out.println("骑士周游算法开始运行------");
        //测试骑士周游算法是否正确
        X = 8;
        Y = 8;
        int row = 1; //马儿走的初始位置的行 从1开始编号 传入的时候row-1即可
        int column = 1; //马儿初始列1
        //创建这个棋盘
        int[][] chessboard = new int[X][Y];
        visited = new boolean[X*Y]; //记录每一个棋盘有没有访问过,访问过就是true 没访问就是false初始
        //测试一下耗时
        long start = System.currentTimeMillis();
        traversalChessboard(chessboard,row-1,column-1,1);

        long end= System.currentTimeMillis();
        System.out.println("耗时:"+(end-start)+"ms");

        //输出棋盘的最后情况 走通了 1-60个点都是1
        for (int[] rows : chessboard) {
            for (int step : rows) {
                System.out.print(step+" ");
            }
            System.out.println();
        }


    }

    public static void traversalChessboard(int[][] chessborad, int row, int colume, int step) {

        /***
         骑士周游问题的算法:
         chessborad 棋盘
         row 当前位置行 0开始
         column 当前位置列 0开始
         step 是第几部 初始位置是第一步
         */
        //总37-1则是正确的位置
        chessborad[row][colume] = step;
        // 4 *8+column =34,个位置,按行树
        visited[row * X + colume] = true; //标记这个位置已经访问

        //获取当前位置可以走的下一个位置的集合
        ArrayList<Point> ps = next(new Point(colume, row)); //colume->x列 rwo y 行
        //对ps中的元素进行非递减排序根据ps内部元素的下一次可选位置元素数量进行非递减排序
        sort(ps);
        while (!ps.isEmpty()) {
            Point p = ps.remove(0); //下一步可以去走的点,取出后继续传给traversalChessborad
            //判断这个点是否已经访过了
            if (!visited[p.y * X + p.x]) { //说明没有访问过  x_row行 y_colume列
                traversalChessboard(chessborad, p.y, p.x, step + 1);
            }
        }
        //判断有没有完成任务,step和该走的步数进行比较
        //如果没有达到数量,则表示没有达到完成任务,将整个棋盘置空0
        //说明 step<x*y  情况有两种
        //1.棋盘目前为止,任然没有走完,
        //2.棋盘走完了,处于一个回溯过程
        if (step < X * Y && !finished) {
            chessborad[row][colume] = 0;
            visited[row * X + colume] = false;
        } else {
            finished = true;
        }

    }

    //根据当前的位置Point对象,计算马儿还有哪些位置Point可以走,并放入一个集合中List,最多8位置
    public static ArrayList<Point> next(Point curPoint) {
        //创建一个List 不能用if-else
        ArrayList<Point> ps = new ArrayList<>();
        //创建一个Point
        Point p1 = new Point();
        //判断是否可以走5
        if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) { //马的走位 可以走左上位置
            //Point p1 = new Point();
            //ps.add(p1);
            ps.add(new Point(p1)); //需要新new一个point,因为每个point 后面的point修改会更改地址,影响list中point的值
        }
        //判断是否可以走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) {
                //先获取到o1这个点的下一个点的个数
                int count1 = next(o1).size();
                int count2 = next(o2).size();
                if (count1<count2){ //非递减
                    return -1;
                }else if (count1==count2){
                    return 0;
                }else{
                    return 1;
                }

                /***
                 // 从小到大 :this‐o   整数  this大 把this放在前面
                 // 从大到小:o‐this
                 */
            }
        });
    }


}

运行结果
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值