骑士游历算法

骑士游历(dp) 设有一个n*m的棋盘(2≤n≤50,2≤m≤50) ,在棋盘上左下角(1,1)处有一个中国 象棋马走的规则为:(1)马走字;(2)只能向右走。当n,m给出之后,同时给出起点的位置和终点的位置,试找出从 起点到终点的所有路径的数目。如图3所示,给出的起点坐标为(1,8),终 点坐标为(3,8),则有2条路径。第1有两个数,表示右上角坐标(n,m) 第2有两个数,表示起点坐标(x1,y1) 第3有两个数,表示终点坐标(x2,y2)输出一个数,表示路径数。... 阅读详情

1 骑士游历问题

  在国际象棋的棋盘(8行×8列)上放置一个马,按照“马走日字”的规则,马要遍历棋盘,即到达棋盘上的每一格,并且每格只到达一次。若给定起始位置(x0,y0),编程探索出一条路径,沿着这条路径马能遍历棋盘上的所有单元格。

  设当前马在棋盘的某个位置(x,y)上,按照规则,下一步有8个方向可走。

  设二维数组mat表示棋盘,每个元素表示棋盘的一格,其值定义如下:

  0表示马未到达过

  Mat[i,j]= -1表示棋盘边界

  自然数 表示马到达该格的步数

2 常规的回溯算法

  2.1 设计思想

  马从棋盘上的某一初始位置(x0,y0)开始,每次选择一个方向k,向前走一格,直到走完64格为止。每走一格,设置数组中相应格的元素值为马走的步数。

  如果选择的方向k=0,表示可能的8种走向都试探不通,不通的原因是走向超出了棋盘范围,或当前位置已经被马访问过。此时马已无路可走,说明前几步走得不对,应该退回去重新换一种走法,这种逐步试探的设计思想称为回溯算法。

  2.2 性能评价

  回溯算法在每一格上朝一个方向盲目地进行试探,遇到在某一格上所有方向都不能走通时,才回到前一格上来试探另一个方向。当每一格上的所有方向都试探过,不能走通时,才做出“走不通”的结论。因此该算法在探索时带有一定的盲目性和随机性,运行效率较低。

3 预见算法

  3.1 设计思想

  回溯算法的思路是可行的,但它的运行效率较低,原因在于每步试探的随机性和盲目性。如果能够找到一种克服这种随机性和盲目性的办法,按照一定规律选择前进的方向,则将增加成功的可能性,运行时间也大为缩短。本文提出的算法在这方面有所突破。

  如果在每步选择方向时,不是任意选择一个方向,而是经过一定的测试和计算,“预见”每条路的“宽窄”,再选择一条最“窄”的路先走,成功的可能性较大。理由是先走“困难的路”,光明大道留在后面。因为每一格迟早都要走到,与其把困难留在后面,不如先走“困难的路”,这样路就会越走越宽,成功的机会就越大。这种方法称为预见算法。

  3.2 实现手段

  为每个方向测定一个值――可通路数,它表示该位置上还有多少条通路。在每一格上对8个方向都进行试探,并分析比较,下一步应该选择可通路数值最小的方向走。


下面表格是有多少个位置可以到达当前这个位置:

23444432
34666643
46888864
46888864
46888864
46888864
34666643
23444432

下面上代码

public class Knight {
    
    private boolean Travel(int firstX, int firstY, int[][] board) {

        // 对应骑士可走的8个方向
        int[] movex = { -2, -1, 1, 2,  2,  1, -1, -2 };
        int[] movey = {  1,  2, 2, 1, -1, -2, -2, -1 };

        // 下一步出路的位置
        int[] nextStepX = new int[board.length];
        int[] nextStepY = new int[board.length];

        // 记录出路的个数
        int[] exitS = new int[board.length];
        int nextX = firstX;
        int nextY = firstY;
        board[nextX][nextY] = 1;

        for (int m = 2; m <= Math.pow(board.length, 2); m++) {
            
            //初始化下一个位置可走的位置的数目
            for (int i = 0; i < board.length; i++) {
                exitS[i] = 0;
            }
            
            int count = 0;
            // 试探8个方向
            for (int i = 0; i < 8; i++) {
                int temI = nextX + movex[i];
                int temJ = nextY + movey[i];

                // 走到边界,路断
                if (temI < 0 || temI > 7 || temJ < 0 || temJ > 7) {
                    continue;
                }

                // 记录下可走的方向
                if (0 == board[temI][temJ]) {
                    nextStepX[count] = temI;
                    nextStepY[count] = temJ;
                    count++;
                }
            }

            // 到这里,cout表示当前点有几种走法。nextStep中存储各种走法的坐标。
            int min = -1;
            if (count == 0) {
                return false;
            }

            if (1 == count) {
                min = 0;
            } else {// 这一步是为了找到下一次走法中最少种走法的那一步
                for (int i = 0; i < count; i++) {
                    for (int j = 0; j < 8; j++) {
                        int temI = nextStepX[i] + movex[j];
                        int temJ = nextStepY[i] + movey[j];
                        if (temI < 0 || temI > 7 || temJ < 0 || temJ > 7) {
                            continue;
                        }
                        
                        // 记录下这个位置可走的方向数
                        if (0 == board[temI][temJ]) {
                            exitS[i]++;
                        }
                    }
                }

                int tem = exitS[0];
                min = 0;

                // 从可走的方向中,寻找最少走的出路
                for (int i = 1; i < count; i++) {
                    if (tem > exitS[i]) {
                        tem = exitS[i];
                        min = i;
                    }
                }
            }

            // 得到最少的出路
            nextX = nextStepX[min];
            nextY = nextStepY[min];
            board[nextX][nextY] = m;
        }

        return true;
    }

    public static void main(String[] args) {

        int firstX, firstY;
        System.out.println("输入起始点(0-7):");
        Scanner scanner = new Scanner(System.in);

        firstX = scanner.nextInt();
        firstY = scanner.nextInt();
        int[][] board = new int[8][8];
        Knight knight = new Knight();

        if (knight.Travel(firstX, firstY, board)) {
            System.out.println("游历完成:");
        } else {
            System.out.println("游历失败!\n");
        }

        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (board[i][j] < 10) {
                    System.out.print(" " + board[i][j]);
                } else {
                    System.out.print(board[i][j]);
                }
                System.out.print(" ");
            }
            System.out.println();
        }
    }
}


参看文献:

http://www.xzbu.com/8/view-1086965.htm

http://www.wuji8.com/meta/266880944.html

http://wenku.baidu.com/link?url=kDUHpgB1ZPtk_CDE8l0q_ekArNkRiOPMHBb-YDcNsupACwajBJt2jm3ySyR2D6b7llZdVhnXVRiGhmdfP7-uNUQ7MuaUO3lFZUhFJ4TkE4C

回溯法解决棋盘问题骑士周游问题 回溯法 基本思想: 对一个包括有很多结点,每个结点有若干个搜索分支的问题,把原问题分解为对若干个子问题求解的算法。 当搜索到某个结点、发现无法再继续搜索下去时,就让搜索过程回溯(即退回)到该结点的前一结点,继续搜索这个结点的其他尚未搜索过的分支; 如果发现这个结点也无法再继续搜索下去时,就让搜索过程回溯到这个结点的前一结点继续这样的搜索过程; 这样的搜索过程一直进到搜索到问题的解或搜索完了全部可搜索分支没有解存在为止。 回溯的处理思想,有点类似枚举搜索。我们枚举所有的解,找到满足期望的解。为了有规律地 阅读详情

相关推荐

[易读易懂] 骑士游历算法 Knight's Tour Problem

1、问题描述在一个N*M的棋盘上,在任意位置放置一个骑士骑士的走"字",和象棋中的一样。问该骑士能否不重复遍历整个棋盘。下面的方法本质还是穷举,所以就写成可以计算出共有多少种不同的遍历方法。2、分析与思路根据题意,骑士走的下一步可能在棋盘上有多种选择(最多8种),需要选择1种,然后继续走下去,直到无处可走。无处可走时有两种情况:情况一:成功完成了遍历,那么接下来就通过回溯(回到上一步的位置,...

MingshanJia的博客 7280

骑士周游国回溯递归解法

在一张国际象棋棋盘上(8*8方格),骑士(knight,)位于任意一个位置。问如何才能让骑士不重不漏的经过棋盘上的每个格?本问题中已知骑士位置(m,n),其中0=<m,n<=8,要求给出骑士走路径,路径可用8*8矩阵输出,其中值表示骑士到达此位置走的步数(初始为1);

基于Java的dfs+预见算法解决骑士游历问题

题目 骑士游历 骑士游历问题是指,在国际象棋棋盘8*8)上,一个要遍历棋盘,即走到棋盘上的每一格,并且每隔只到达一次。设码在棋盘的某一位置(x,y)上,按照“走”的规则,下一步有8个方向走,如图所示。若给定起始位置(x0,y0),使用站和队探索出一条遍历棋盘的路径。 8 1 7 2

AyagiKei的博客 2082

骑士巡游问题(问题),用回溯法实现的

问题描述】 骑士巡游问题:国际象棋棋盘上任意给定的方格开始移动骑士,相继地到达所有的64个方格,进入每个方格一次且仅进入一次。

图应用:骑士周游问题

骑士周游问题一个国际象棋棋盘上,一个棋子""(骑士),按照"马走"的规则,从一个格子出发,要走遍所有棋盘格恰好一次 把一个这样的走棋序称为一次"周游"8x8国际象棋棋盘上,合格的"周游"数量有1.305x10^35这么多,走棋过程中失败的周游就更多了 采用图搜索算法,是解决骑士周游问题最容易理解和编程的方案之一 解决方案还是分为两步: 首先将合法走棋次序表示为一个采用图搜索算法搜寻一个长度为(X-1)的路径,路径上包含每个顶点恰一次 将棋盘和走棋步骤构建为图的思路

Leopold的博客 1409

骑士遍历问题回溯法

文章目录参考概述思路 参考 link 概述 骑士游历问题是放在n*n的国际象棋棋盘上的一个按照马走""字的规则是否能够不重复地走遍棋盘的每个格。 思路 骑士最后要遍历所有的点。每次运动最多有八种方式。已经去过的点不会再去。 解空间:每次有八种方式走到下一个点(剪枝:剪掉去过的点和没法到达的点)没走过的格子标0,走过的标1.为了方便起见,边界直接标1。 然后试着在地图外标了一圈1,发现自己...

weixin_44814121的博客 3442

C++骑士游历算法设计与实现

骑士游历问题(Knight’s Tour)是国际象棋与计算机科学交汇的一个经典难题。其核心目标是:在标准棋盘(如8×8)上,让一个骑士从任意起始位置出发,按照国际象棋规则,不重复地走遍所有格子。该问题不仅考验算法设计能力,还广泛涉及图论、递归和回溯等编程思想。该问题最早可追溯至公元9世纪的阿拉伯与印度文献,18世纪数学家欧拉曾对其进深入研究,成为图论中哈密顿路径问题的特例。在现代,它被用于测试人工智能搜索策略、路径规划算法,甚至用于密码学中的随机路径生成。

weixin_30248619的博客 1003

java编写类骑士游历_[基于Java的骑士游历问题的预见算法]骑士游历问题

摘要:骑士游历问题是经典的NP问题。在骑士游历问题常规算法的基础上,提出一个新的算法――预见算法,用Java实现该算法,提高程序的运效率。   关键词:骑士游历;预见;Java算法1 骑士游历问题国际象棋棋盘(8×8)放置一个按照马走字”的规则,要遍历棋盘,即到达棋盘上的每一格,并且每格只到达一次。若给定起始位置(x0,y0),编程探索出一条路径,沿着这条路径能遍历棋盘上的...

weixin_28937805的博客 588

[递归算法]骑士游历问题

题目:[递归算法]骑士游历问题 题目描述 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如图11.2.1。在棋盘上任一点有一个中国象棋马走的规则为:1.马走字 2.只能向右走。 当N,M 给出之后,同时给出起始的位置和终点的位置,试找出从起点到终点的所有路径的数目。例如:(N=10,M=10)(1,5)(起点)(3,5)(终点)。应输出2(即由(1,5)(3,5)共有2条路径。 输入 n,m,x1,y1,x2,y2(分别表示n,m,起点坐标,终点坐标) 输出 路径数目(若不存在从起点

herq456uh的博客 2376

c语言骑士游历优化算法,骑士游历问题(C语言代码)

关于骑士游历问题,大家可以想到的方法是回溯法和贪心算法回溯法的时间复杂度比较高,贪心算法的时间复杂度就好多了。骑士游历问题问题描述:棋盘大小是8*8骑士棋盘任一方格开始游历。要求骑士游历棋盘的每一个方格且每个方格只游历一次。输出骑士游历路径。解决思路:dir0、dir1…dir7由小到大排,每次选择具有最少出口的方向,假设为dir0。如果骑士走到第n步时,没有出口可以选择,同时,骑士未完...

weixin_32002829的博客 1418

POJ2488-A Knight's Journey【骑士游历

北大POJ2488-A Knight's Journey 解题报告+AC代码

JavaScript实现骑士游历算法

骑士游历算法一个回溯算法,通过尝试不同的路径来解决问题。具体而言,对于给定的起始位置,我们尝试沿着骑士可能的移动方向进移动,直到棋盘上所有的方格都被访问过为止。如果当前路径不能完成游历,则回溯到上一步,选择其他可能的移动方向。骑士游历问题一个经典的数学和计算机科学问题,它要求在国际象棋棋盘上找到一条路径,使得骑士可以恰好访问棋盘的每个方格一次。在这篇文章中,我们将使用JavaScript来实现骑士游历算法,并探讨其工作原理。JavaScript实现骑士游历算法

ByteZenith的博客 103

算法设计】回溯法算法设计——骑士游历问题(C++实现)

骑士游历问题 问题描述 在国际象棋棋盘8×8)上放置一个按照马走字”的规则,要遍历棋盘,即到达棋盘上的每一格,并且每格只到达一次。 若给定起始位置(x0,y0),编程探索出一条路径,沿着这条路径能遍历棋盘上的所有单元格 算法思想和解题思路 棋盘上的某一初始位置(x0,y0)开始,每次选择一个方向k,向前走一格,直到走完64格为止。每走一格,设置数组中相应格的元素值为马走的步数。 如果选择的方向k=0,表示可能的8种走向都试探不通,不通的原因是走向超出了棋盘范围,或当前位置已经被

努力让自己的能力配得上梦想. 1704

c语言骑士游历优化算法,骑士游历骑士巡游(C语言)课程设计.doc

存档资料 成绩:华东交通大学理工学院课 程 设 计 报 告 书所属课程名称 数据结构题 目   骑士游历分 院专业班级学  号学生姓名 黄锦辉指导教师2012 年 6月 15 目 录第1章 课程设计内容及要求1第2章 功能的说明与实现22.1 程序功能模块22.2 程序功能模块...

weixin_32858247的博客 641

骑士游历问题——程序设计艺术与方法实验二 搜索算法的实现

骑士游历问题——程序设计艺术与方法实验二 搜索算法的实现 骑士游历问题: 在国际棋盘上使一个骑士遍历所有的格子一遍且仅一遍,对于任意给定的顶点,输出一条符合上述要求的路径。 分析: 国际象棋以及国际象棋骑士的走法 国际象棋棋子放在格子中。国际象棋骑士可以走八个方位。走法是走“”字,或英文字母大写的“L”形:即先向左(或右)走1格,再向上(或下)走2格;或先向左(或右)走2格,再向上(或下)走1格。国际象棋可以跳过路上的其他棋子,不受拐脚的限制。 解题需要我们可以把格子抽象成一个点,那么国际象棋骑士

小哨的博客 1158

回溯算法基础---皇后问题骑士游历,迷宫求解

回溯法(又叫试探法)是属于穷举的子集,对于许多的问题,当我们需要找到某些解集或者满足某种要求的最优解的时候,回溯法往往是很朴素和简单的一种算法。从数学的角度来说,比较适合一些组合数较大的问题,比如五子棋博弈算法,最短路径(最小代价)等,使用回溯算法往往会得到正确的答案,但是回溯算法由于是采用穷举的方式,所以运时间一般是很大的,当然可以通过各种优化手段来降低,而许多的问题--------回溯法是最

Vurteon的专栏 5111

贪心算法实现骑士游历问题(C语言完整代码)

贪心算法是一种在特定条件下能高效求解问题算法策略,其核心思想是在每一步选择中都做出当前状态下最优的局部选择,期望通过这样的局部最优解累积出全局最优解。骑士游历问题作为经典的路径搜索问题,要求骑士棋盘上不重复地走遍所有格子,非常适合用于探讨贪心算法的应用效果。本章将简要介绍贪心算法的基本原理及其在骑士游历问题中的适用性,为后续章节的实现与优化打下理论基础。骑士游历问题国际象棋中的一个经典问题,要求一个骑士棋盘的某一位置出发,按照国际象棋的规则走遍所有方格且每个方格仅访问一次。

weixin_42575109的博客 877

JAVA中的回溯算法解空间树,八皇后问题以及骑士游历问题超详解

设码在棋盘的某一位置(x,y)上,按照“走”的规则,下一步有8个方向走,如图所示。若给定起始位置(x0,y0),使用站和队探索出一条遍历棋盘的路径。,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横、纵或斜线上吗,问有多少种摆法。整体的思路就是不断递归下一个元素,然后从currentSubset中移除最后添加的元素,进回溯,准备处理下一个元素。为背景的问题:如何能够在8×8国际象棋棋盘放置八个。意思就是一个集合s所有的子集的集合。

2302_79993788的博客 1565
上一篇: 老鼠走迷宫递归算法
下一篇: 八皇后算法
sb___itfk
博客等级 码龄12年 19粉丝 23原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值