马踏棋盘(骑士周游问题)

马踏棋盘问题(骑士周游问题)

  • 实际上是图的深度优先搜索(DFS)的应用。
  • 如果使用回溯(就是深度优先搜索)来解决,假如马儿踏了53个点,如图:走到了第53个,坐标(1,0),发现已经走到尽头,没办法,那就只能回退了,查看其他的路径,就在棋盘上不停的回溯…… ,思路分析+代码实现
  • 使用贪心算法(greedyalgorithm)进行优化。解决马踏棋盘问题.

/**
 * 〈马踏棋盘 算法〉
 *
 * @author LZ
 * @create 2019/9/29
 * @since 1.0.0
 */
public class HorseChessboard {
    /**
     * 列数
     */
    private int width;
    /**
     * 行数
     */
    private int height;
    /**
     * 访问记录
     */
    private boolean[] visited;
    /**
     * 棋盘
     */
    private int[][] chessboard;

    /**
     * 是否完成
     */
    private boolean finished = false;

    public static void main(String[] args) {
        HorseChessboard horseChessboard = new HorseChessboard(8, 8);
        long start = System.currentTimeMillis();
        horseChessboard.start(new Point(0, 0), 1);
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        horseChessboard.show();
    }

    /**
     * 初始化属性
     *
     * @param width  棋盘 宽度
     * @param height 棋盘 高度
     */
    public HorseChessboard(int width, int height) {
        this.width = width;
        this.height = height;
        this.chessboard = new int[width][height];
        this.visited = new boolean[width * height];
        Arrays.fill(this.visited, false);
    }

    /**
     * 开始游戏
     *
     * @param p    起始点
     * @param step 第几步
     */
    public void start(Point p, int step) {
        // 标记该点第几步
        this.chessboard[p.x][p.y] = step;
        // 标记以访问过
        int index = p.y * width + p.x;
        this.visited[index] = true;
        // 寻找下一个
        List<Point> ps = findNextStep(p);
        sort(ps);
        while (!ps.isEmpty()) {
            Point point = ps.remove(0);
            // 判断是否访问过
            if (!in(point)) {
                this.start(point, step + 1);
            }
        }
        //  回溯
        if (step < width * height && !finished) {
            chessboard[p.x][p.y] = 0;
            visited[p.y * width + p.x] = false;
        } else {
            finished = true;
        }
    }

    /**
     * 寻找下步可能性
     *
     * @param p 当前点
     * @return list
     */
    private List<Point> findNextStep(Point p) {
        List<Point> ps = new ArrayList<>();
        Point nextPoint = new Point();
        // 0
        if ((nextPoint.x = p.x + 2) < width && (nextPoint.y = p.y + 1) < height) {
            ps.add(new Point(nextPoint));
        }
        // 7
        if ((nextPoint.x = p.x + 1) < width && (nextPoint.y = p.y + 2) < height) {
            ps.add(new Point(nextPoint));
        }
        // 6
        if ((nextPoint.x = p.x - 1) >= 0 && (nextPoint.y = p.y + 2) < height) {
            ps.add(new Point(nextPoint));
        }
        // 5
        if ((nextPoint.x = p.x - 2) >= 0 && (nextPoint.y = p.y + 1) < height) {
            ps.add(new Point(nextPoint));
        }
        // 4
        if ((nextPoint.x = p.x - 2) >= 0 && (nextPoint.y = p.y - 1) >= 0) {
            ps.add(new Point(nextPoint));
        }
        // 3
        if ((nextPoint.x = p.x - 1) >= 0 && (nextPoint.y = p.y - 2) >= 0) {
            ps.add(new Point(nextPoint));
        }
        // 2
        if ((nextPoint.x = p.x + 1) < width && (nextPoint.y = p.y - 2) >= 0) {
            ps.add(new Point(nextPoint));
        }
        // 1
        if ((nextPoint.x = p.x + 2) < width && (nextPoint.y = p.y - 1) >= 0) {
            ps.add(new Point(nextPoint));
        }
        return ps;
    }

    /**
     * 展示
     */
    public void show() {
        for (int[] ints : this.chessboard) {
            for (int anInt : ints) {
                System.out.print(anInt + "\t");
            }
            System.out.println();
        }
    }

    /**
     * 判断是否访问过
     *
     * @param p 待判断的端点
     * @return boolean
     */
    private boolean in(Point p) {
        return this.visited[p.y * width + p.x];
    }

    /**
     * 进行非递减排序
     *
     * @param ps 待排序的集合
     */
    public void sort(List<Point> ps) {
        ps.sort((item1, item2) -> {
            int count1 = findNextStep(item1).size();
            int count2 = findNextStep(item2).size();
            return Integer.compare(count1, count2);
//            if (count1 < count2) {
//                return -1;
//            } else if (count1 == count2) {
//                return 0;
//            } else {
//                return 1;
//            }
        });
    }

原文地址:https://www.cnblogs.com/MND1024/p/11611478.html

时间: 2024-10-11 07:38:12

马踏棋盘(骑士周游问题)的相关文章

马踏棋盘代码分析

(因为最近数据结构讲到图和网,听是能听懂,可是一到代码上,就发现问题很多,因此将马踏棋盘的代码拿出来分析下,貌似有些不对头,其实呢是因为不想写其余的作业,所以找个借口) 说到马踏棋盘,这样说,就是一个8*8的棋盘,指定一个位置,让马走日字,将棋盘上的点全部走完. 先说说思路:首先指定位置,在这个位置的基础上走一个位置,然后再在这个基础上走日字,现在面临一个问题,要是走着走着,突然有一次,就那么的卡住在那里了,怎么走都不行,可是全局看下,会发现,还有空点没有踏到,那么怎么办?看来这条路不通了,那就

回溯算法(马踏棋盘)

近期学习了回溯算法于是自己写了马踏棋盘的递归以及非递归方式的代码: 运行效果如下: (本人水平有限,若有不足之处欢迎大家交流)

马踏棋盘的c语言实现(一.遍历法)

题目很简单呀!!! 在国际象棋的棋盘上,将马随意放置,之后走日字,走完即可. 要求:8×8的棋盘 遍历算法: 可以说是碰运气,当你确定在某一位置时,根据规则你自然有了八种选择,                   2   3          1       4           H           8       6         7   5                                         分别是 X=   {i-2, i-1, i+1, i+2, i+

马踏棋盘问题-贪心(matlab&amp;c++)

1.问题描述 将马随机放在国际象棋的Board[0-7][0-7]的某个方格中,马按走棋规则进行移动,走遍棋盘上全部64个方格.编制非递归程序,求出马的行走路线,并按求出的行走路线,将数字1,2,…,64依次填入一个8×8的方阵,输出之. 2.matlab代码 clear all clc chessboard=zeros(8);%初始化 DirX=[2 1 -1 -2 -2 -1 1 2];%方向向量 DirY=[1 2 2 1 -1 -2 -2 -1]; stack(1).x=0; stack

逃离大厦第80关与马踏棋盘

今天我在玩一款逃离大厦的解密游戏.在跨越了重重障碍来到了第八十关.这一关很有意思 每次点击都会直接冲到底,要求填满所有空白的地方. 本来很容易,但是很不幸,一旦点击了就不能修改,楼主于是想到了马踏棋盘,终于可以学以致用了于是毫不犹豫 上代码 #include <stdio.h> #include <stdlib.h> #define N 5+2 typedef struct { int a[N][N]; int lstep[4]; int rstep[4]; int cnt; }H

马踏棋盘递归所有解

这次马踏棋盘是用递归实现的,而且可以弄出来所有解,当时电脑跑的最快的都有40多万解了,这个也可以看你电脑cpu好坏,一般超级本跑不动.这是实际上和八皇后是同一种性质的问题,都用到了回溯的思想,有接进行下一个,不行了退回去,在进行尝试.不多说了,直接上代码: #include<stdio.h> #include <stdlib.h> #include<conio.h> #define N 8 int cnt=1; // 记录马的位置 int n=1; int chess[

剑指Offer_12_矩阵中的路径(参考问题:马踏棋盘)

题目描述  请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子. 例如: a   b  c   e s   f   c   s  a  d   e   e  矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后

马踏棋盘--深度优先搜索

题目描述: 8 * 8 的棋盘,"马" 初始位置于 <0,0>,按 "日" 行走,一次性不重复踏遍整个棋盘,共有多少种方案?并打印行走方案. 补充: 这里测试8阶棋盘,貌似方案数会非常多,小生程序效率貌似不怎么样,十几分钟没跑完,所以拿5阶来测试.只需要改变代码中的 #define X 5 即可测试任何阶马踏棋盘游戏,阶数越高,程序运行时间将会越长.(8阶都不知道要跑到什么时候..) 代码中 void CHorse::funcStart() { func

小甲鱼数据结构和算法--马踏棋盘(骑士周游问题)

代码如下: #include<stdio.h> #include<time.h> #define X 5 #define Y 5 int chess[X][Y]; void printChess(){ int i,j; printf("This is horse Chess:\n"); for( i=0;i<X;i++){ for(j=0;j<Y;j++){ printf("%2d\t",chess[i][j]); } print