Java学习——算法——骑士周游(贪心优化)

学习尚硅谷韩顺平老师的Java数据结构笔记,详情请移步网站
1、游戏介绍
(1) 马踏棋盘算法也被称为骑士周游问题
(2) 将马随机放在国际象棋的 8×8 棋盘 Board[0~7][0~7]的某个方格中,马按走棋规则(马走日字)进行移动。要求每个方格只进入一次,走遍棋盘上全部 64 个方格
在这里插入图片描述
2、代码实现
(1) 马踏棋盘问题(骑士周游问题)实际上是图的深度优先搜索(DFS)的应用。
(2) 如果使用回溯(就是深度优先搜索)来解决,假如马儿踏了 53 个点,如图:走到了第 53 个,坐标(1,0),发现已经走到尽头,没办法,那就只能回退了,查看其他的路径,就在棋盘上不停的回溯…… ,思路分析+代码实现
 对第一种实现方式的思路图解
在这里插入图片描述
(3) 分析第一种方式的问题,并使用贪心算法(greedyalgorithm)进行优化。解决马踏棋盘问题.
在这里插入图片描述

package Algorithm.Horse;

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

/**
 * 马踏棋盘问题
 */
public class HorseChessboard {
    private static int X;//棋盘列数
    private static int Y;//棋盘行数
    private static boolean visited[];//标记当前位置是否被访问
    private static boolean finished;//标记棋盘所有位置是否都被访问 如果为true 表示成功

    public static void main(String[] args) {
        X = 8;
        Y = 8;
        int row = 1;//初始位置
        int column = 1;
        int[][] chessboard = new int[X][Y];
        visited = new boolean[X* Y];
        long start = System.currentTimeMillis();//开始时间
        traversalChessboard(chessboard,row-1,column-1,1);
        long end = System.currentTimeMillis();//结束时间
        System.out.println("耗时 " + (end - start));

        for (int[] cows : chessboard){
            for (int step : cows){
                System.out.print(step + "\t");
            }
            System.out.println();
        }
    }

    /**
     * 骑士周游算法
     * @param chessboard 棋盘
     * @param row 骑士当前位置的横坐标 行
     * @param column 骑士当前位置的纵坐标 列
     * @param step 是第几步
     */
    public static void traversalChessboard(int[][] chessboard, int row, int column, int step){
        chessboard[row][column] = step;
        visited[row * X + column] = true;//标记当前位置已访问
        ArrayList<Point> ps = next(new Point(column, row));//x代表的是列
        //对ps内的所有点的下一步的位置的数目进行非递减排序
        sort(ps);//贪心算法,选最少的
        //遍历ps
        while (!ps.isEmpty()){
            Point p = ps.remove(0);//取出下一个可以走的位置
            //判断该点是否已经访问过
            if (!visited[p.y* X + p.x]){
                traversalChessboard(chessboard,p.y,p.x,step+1);
            }
        }
        //判断骑士是否完成了任务,使用step和应该走的步数比较
        if (step < X * Y && !finished){//表示没有完成任务,将整个棋盘置0
            chessboard[row][column] = 0;
            visited[row *X +column] = false;
        }else {
            finished = true;
        }
    }

    /**
     * 根据当前位置计算还能走哪些位置
     * @param curPoint 当前位置
     * @return 可以走的位置的数组
     */
    public static ArrayList<Point> next(Point curPoint){
        ArrayList<Point> ps = new ArrayList<>();
        Point p1 = new Point();
        //表示可以走的8个位置
        if ((p1.x = curPoint.x - 2) >= 0 &&  (p1.y = curPoint.y -1) >=0 ){
            ps.add(new Point(p1));
        }
        if ((p1.x = curPoint.x - 1) >= 0 &&  (p1.y = curPoint.y -2) >=0 ){
            ps.add(new Point(p1));
        }
        if ((p1.x = curPoint.x + 1) < X &&  (p1.y = curPoint.y -2) >=0 ){
            ps.add(new Point(p1));
        }
        if ((p1.x = curPoint.x + 2) < X &&  (p1.y = curPoint.y -1) >=0 ){
            ps.add(new Point(p1));
        }
        if ((p1.x = curPoint.x - 2) >= 0 &&  (p1.y = curPoint.y +1) < Y ){
            ps.add(new Point(p1));
        }
        if ((p1.x = curPoint.x - 1) >= 0 &&  (p1.y = curPoint.y +2 ) < Y){
            ps.add(new Point(p1));
        }
        if ((p1.x = curPoint.x + 2) < X &&  (p1.y = curPoint.y +1) < Y ){
            ps.add(new Point(p1));
        }
        if ((p1.x = curPoint.x  +1) < X &&  (p1.y = curPoint.y +2) < 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) {
                //获取点1的下一步的所有位置个数
                int size1 = next(o1).size();
                //获取点2的下一步的所有位置个数
                int size2 = next(o2).size();
                if (size1 < size2){
                    return -1;
                }else if (size1 == size2){
                    return 0;
                }else {
                    return 1;
                }
            }
        });
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值