骑士周游问题

在一个国际象棋棋盘上,一个棋子"马"(骑士),按照"马走日"的规则,从一个格子出发,要走遍所有棋盘格恰好一次

  • 把一个这样的走棋序列称为一次"周游"

在8x8的国际象棋棋盘上,合格的"周游"数量有1.305x10^35这么多,走棋过程中失败的周游就更多了

采用图搜索算法,是解决骑士周游问题最容易理解和编程的方案之一

解决方案还是分为两步:

  • 首先将合法走棋次序表示为一个图
    • 采用图搜索算法搜寻一个长度为(行X列-1)的路径,路径上包含每个顶点恰一次

将棋盘和走棋步骤构建为图的思路

  • 将棋盘格作为顶点
  • 按照“马走日”规则的走棋步骤作为连接边
  • 建立每一个棋盘格的所有合法走棋步骤能够到达的棋盘格关系图
  • 示例代码
def genlegalMoves(x,y,bdSize):newMoves = []moveOffsets = [(-1,-2),(-1,2),(-2,-1),-2,1),( 1,-2),(1,2),( 2,-1),( 2,1)]    #马可以走的八个格子for i in moveOffsets:newX = x + i[0]newY = y + i[1]if legalCoord(newX,bdSize) and legalCoord(newY, bdSize):         #合法的坐标newMoves.append((newX,newY))return newMovesdef legalCoord(x, bdSize):if x >= 0 and x < bdSize:              #确认不会走出棋盘return Trueelse:return False

构建走棋关系图

  • 示例代码
def knightGraph(bdSize):ktGraph = Graph()for row in range(bdSize):for col in range(bdSize):          #遍布每个格子nodeId = posToNodeId(row, col, bdSize)newPositions = genLegalMoves(row,col,bdSize)             #新的位置,单步合法走棋for e in newPositions:nid = posToNodeId(e[0],e[1],bdSize)ktGraph.addEdge(nodeId,nid)  #添加边及顶点return ktGraphdef posToNodeId(row,col,bdSize):return row*bdSize+col

8x8棋盘生成的图

具有336条边,相比起全连接的4096条边,仅8.2%,还是稀疏图

骑士周游算法实现

用于解决骑士周游问题的图搜索算法是深度优先搜索(Depth First Search)

相比前述的广度优先搜索,其逐层建立搜索树的特点

深度优先搜索是沿着树的单支尽量深入向下搜索

  • 如果到无法继续的程度还未找到问题解,就回溯上一层再搜索下一支

DFS的两个实现算法

  • 一个DFS算法用于解决骑士周游问题,其特点是每个顶点仅访问一次
  • 另一个DFS算法更为通用,允许节点被重复访问,可作为其他图算法的基础

深度优先搜索解决骑士周游的关键思路

  • 如果沿着单支深入搜索到无法继续(所有合法移动都已经被走过了)时
  • 路径长度还没有到达预定值(8X8棋盘为63),那么清除颜色标记,返回到上一层,换一个分支继续深入搜索

引入一个栈来记录路径

  • 并实施返回上一层的回溯操作

代码实现

def knightTour(n, path, u, limit):    #n:层次,path:路径, u:当前顶点, limit:搜索总深度u.setColor('gray')path.append(u)if n < limit:nbrList = list(u.getConnections())        #对所有合法移动逐一深入i = 0done = Falsewhile i < len(nbrList) and not done:if nbrList[i].getColor() == 'white':    #选择白色未经过的顶点深入done = knightTour(n+1, path, nbrList[i], limit)i = i + 1if not done: #  准备放弃path.pop()u.setColor('white')        #都无法完成总深度,回溯,试本层下一个顶点else:done = Truereturn done

图解

其中一个解

  • 从底下正中央

算法分析与改进

上述算法的性能高度依赖于棋盘大小:

  • 5X5棋盘,约1.5秒可以得到一个周游路径
  • 8X8棋盘,则要半个小时以上才能得到一个解

目前实现的算法,其复杂度为O(k^n),其中n是棋盘格数目

  • 这是一个指数时间复杂度的算法!其搜索过程表现为一个层次为n的树

即便是指数时间复杂度算法也可以再实际性能上加以大幅度改进

  • 对nbrList的灵巧改造,以特定方式排列顶点访问次序,使8X8棋盘的周游路径搜索时间降低到秒级

这个改进算法被特别以发明者名字命名:Warnsdorff算法

初始算法中,直接以原始顺序来确定深度优先搜索的分支次序

新的算法,仅修改了遍历下一格的次序

  • 将u的合法移动目标棋盘格排序为:具有最少合法移动目标的格子优先搜索
def orderByAvail(n):resList = []for v in n.getConnections():if v.getColor() == 'white':c = 0for w in v.getConnections():if w.getColor() == 'white':c = c + 1resList.append((c,v))resList.sort(key=lambda x: x[0])return [y[1] for y in resList]

采用先验的知识来改进算法性能的做法,称作为"启发式规则heuristic"

  • 启发式规则经常用于人工智能领域;
  • 可以有效的减小搜索范围,更快达到目标等等;
  • 如棋类程序算法,会预先存如棋谱、布阵口诀、高手习惯等"启发式规则".能够在最短的时间内从海量的棋局落子点搜索树中定位最佳落子。

图应用:骑士周游问题相关推荐

  1. 2.17_knight_tour_骑士周游问题 (深度优先 DFS)

    --- 骑士周游问题 ---在国际象棋棋盘上,一个"骑士"按照"马走日"的规则从一个格子出发,走遍所有棋盘格恰好一次,即为一次周游思路 (深度优先 - Dept ...

  2. 骑士周游(dfs+greedy)

    骑士周游(DFS+Greedy): 提示:马踏棋盘问题 也称 骑士周游问题 记录一道dfs+greedy的题目, 这道题能够帮助我们更好的理解dfs中的优化问题 题目描述: 提示:马踏棋盘问题(骑士周 ...

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

    1,马踏棋盘算法介绍 马踏棋盘问题也被称为骑士周游问题 将马随机放在国际象棋的8*8的棋盘中的某个格子里,马按照走棋规则(日子)进行移动.要求每个方格只进入一次,走遍64个方格 2,马踏棋盘算法思路分 ...

  4. Java对马踏棋盘问题(骑士周游问题)的实现

    14.10.2 马踏棋盘游戏代码实现 马踏棋盘问题(骑士周游问题)实际上是图的深度优先搜索(DFS)的应用. 如果使用回溯(就是深度优先搜索)来解决,假如马儿踏了 53 个点,如图:走到了第 53 个 ...

  5. 常用十大算法 非递归二分查找、分治法、动态规划、贪心算法、回溯算法(骑士周游为例)、KMP、最小生成树算法:Prim、Kruskal、最短路径算法:Dijkstra、Floyd。

    十大算法 学完数据结构该学什么?当然是来巩固算法,下面介绍了十中比较常用的算法,希望能帮到大家. 包括:非递归二分查找.分治法.动态规划.贪心算法.回溯算法(骑士周游为例).KMP.最小生成树算法:P ...

  6. 【数据结构与算法】马踏棋盘(骑士周游世界)算法

    一,基本介绍 1)马踏棋盘算法也称为骑士周游问题 2)将马随机放在国际象棋的8 × 8棋盘Board[0~7] [0~7]的某个方格中,马按走棋规则(马走日字)进行移动.要求每个方格只进入一次,走遍棋 ...

  7. 马踏棋盘算法(骑士周游)

    思路分析 代码实现 package com.atguigu.horse;import java.awt.*; import java.util.ArrayList; import java.util. ...

  8. 马踏棋盘算法(骑士周游)+贪心优化

    思路分析 代码实现 package com.atguigu.horse;import java.awt.*; import java.util.ArrayList; import java.util. ...

  9. 骑士周游(马走棋盘)及剪枝分析

    一.题目 在n x n棋盘(有n x n个格点的棋盘)的某个格点上有一个中国象棋马,马走日字. 求一条周游棋盘的路径,使得马能够从起始位置起沿着该路径每个格点恰好走一次最后回到出发位置. 二.思路 1 ...

  10. 骑士周游算法 c语言_C语言经典算法04--骑士走棋盘(骑士旅游:Knight tour)

    说明:骑士旅游(Knight tour)在十八世纪初倍受数学家与拼图迷的注意,它什么时候被提出已不可考,骑士的走法为西洋棋的走法,骑士可以由任一个位置出发,它要如何走完[所有的位置? 解法:骑士的走法 ...

最新文章

  1. JS基础入门篇(一)
  2. 如何从Docker容器内部连接到计算机的本地主机?
  3. matlab中矩阵的各种分解
  4. arthas使用示例:profiler火焰图(CPU)
  5. Echarts与Highcharts的比较
  6. [iOS Animation]-CALayer 性能优化实例
  7. 第一节:从面向对象思想(oo)开发、接口、抽象类以及二者比较
  8. python3所支持的整数进制_Python3快速入门(三)——Python3标准数据类型
  9. oracle10g 监听服务无法启动
  10. lnmp 清除mysql日志,军哥LNMP 如何关闭 Mysql 日志,并且删除 mysql-bin.0000*日志文件...
  11. python字符串基本操作符有哪些_Python字符串及基本操作(入门必看)!!
  12. 浅谈三层架构 通过这个,+Java开发模式经验。终于相通了,动软到底是为什么这么做...
  13. 基于51单片机控制步进电机正反转
  14. 单片机开发软件keil4和proteus的使用教程(超详细)_☆往事随風☆的博客
  15. 计算机毕业设计-ssm超市进销存管理系统(项目+类似文档)超市仓库管理系统javaweb-超市库存预警管理系统源码
  16. MCSA / Windows Server 2016各版本的功能及比较,安装需求及选项
  17. 带阵列的服务器如何重装系统,带阵列服务器系统重装
  18. 继电器互锁功能的实现
  19. linux命令 trtest,Linux tr命令的使用方法
  20. 为什么很多企业要自研CRM系统,而不够买SAAS云服务提供的CRM系统或SCRM系统?...

热门文章

  1. dfuse for EOSIO v0.1.0-beta4 版本更新说明
  2. html如何让字体变形,jquery实现字体变形特效-css字体变成圆形
  3. 摩根大通从AWS和Azure挖人,云计算人才大战开始
  4. vps一键测速脚本,包含vps配置测试、速度测试和回程路由测试
  5. Latex的pdf合并
  6. 浏览器有网微信没网络连接服务器,电脑可以登陆微信但是浏览器无法联网是怎么回事儿...
  7. kubectl 命令详解(三十三):rollout resume
  8. Java第十二周作业
  9. 2022-2028全球与中国电热毯市场现状及未来发展趋势
  10. 如何root安卓手机_超级神器——安卓端的手机虚拟机,手机中的手机(支持root,xp框架)...