基于贪心算法的马踏棋盘哈密顿回路问题
基于贪心算法的马踏棋盘哈密顿回路问题
Github 链接
问题分析
马踏棋盘其实相当于一个解空间的搜索问题,而遍历到每一个节点并要求最后可以回到起点本质上是一个哈密顿回路问题
目前大部分马踏棋盘的相关问题并不要求回到起点,然后实际上在不重复的走完全盘的可行解中寻找最后可以回到起点的最优解更为困难。可行解有非常多个,然而最优解虽然比可行解少得多,但也并不少
问题在于,这个搜索空间十分的庞大,倘若不考虑棋盘位置约束与遍历次数限制,解空间大小将达到指数级的庞大规模。但是即便在这些解中加上棋盘限制与单次访问等的剪枝条件,为了在可行解(64个节点仅各访问一次)中搜寻到可以回到起点的最优解仍然是非常困难的。倘若仅仅固定八个可行方向的顺序,使用深度优先的递归来实施搜索,效率将会非常低下。
这是因为对于靠近边界的四个顶点的区域来说,如果不能尽快的遍历完这些区域,而是按照固定的顺序来遍历会十分容易造成“死节点”,将来不可能再次访问。而与此同时,程序还在徒劳的往更深的方向搜索,极大的影响搜索效率。
贪心算法的改进
为了尽量较快的遍历完一个边界区域,我们应当尽量“靠边走”。故而有以下的贪心策略。再对八个方向进行顺序的考虑时,优先选取拥有较少可行孙节点的子节点方向(边界区域),并给每一个方向一个权值由于方向的排序。代码如下
void sort_direction(int x, int y) {int x_new, y_new, xx_new, yy_new;int score[Row] = { Row,Row,Row,Row,Row,Row,Row,Row}; // 定义不同方向的得分权值for (int i = 0; i < Row; i++) {int count = 0;x_new = x + deta_x[i];y_new = y + deta_y[i];if (check(x_new, y_new) == 1) { // 检查点a[xx][yy]是否满足条件 for (int j = 0; j < Columns; j++) {xx_new = x_new + deta_x[j];yy_new = y_new + deta_y[j];if (check(xx_new, yy_new) == 1) // 检查点a[xx][yy]是否满足条件 count++;}}score[i] = count;}sort_index(score, sorted, Row); // 快速排序
}
基于此思想再结合深度优先的递归算法基本可以秒出(0.02s以内)绝大多数点(除去四个边界顶点与(8,7)这个点)的哈密顿回路。
42 | 33 | 26 | 9 | 62 | 13 | 28 | 11 |
---|---|---|---|---|---|---|---|
25 | 8 | 41 | 58 | 27 | 10 | 63 | 14 |
34 | 43 | 32 | 61 | 40 | 59 | 12 | 29 |
7 | 24 | 57 | 50 | 31 | 64 | 15 | 52 |
44 | 35 | 46 | 39 | 60 | 51 | 30 | 1 |
23 | 6 | 49 | 56 | 47 | 18 | 53 | 16 |
36 | 45 | 4 | 21 | 38 | 55 | 2 | 19 |
5 | 22 | 37 | 48 | 3 | 20 | 17 | 54 |
完整代码见文末
###边界顶点的优化
即便基于以上贪心算法改进后,边界上的四个顶点仍然较难求出最优解。归其本质为边界顶点有且仅有两个节点联通,故而若唯一的回路在中间递归过程被占用的话便永远也回不到起点。故而优化方式便是强行定义一个规则:让唯一的回路关键节点最后一次访问
if (x_0 == 1 && y_0 == 1) {if (deep <= Total_step - 1)qipan[2][1] = 1;else qipan[2][1] = 0;}if (x_0 == 1 && y_0 == Columns) {if (deep <= Total_step - 1)qipan[2][Columns-2] = 1;else qipan[2][Columns - 2] = 0;}if (x_0 == Row && y_0 == Columns) {if (deep <= Total_step - 1)qipan[Row-3][Columns - 2] = 1;else qipan[Row - 3][Columns - 2] = 0;}if (x_0 == Row && y_0 == 1) {if (deep <= Total_step - 1)qipan[Row - 2][2] = 1;else qipan[Row - 2][ 2] = 0;}
加上以上改进后四个节点的一条哈密顿解亦可秒出
上图便是规模为8时各个顶点不重复的走完全盘但是没有回到起点的次数、可以看出边界区域上的回溯次数明显大于中心区域的点。特别的,(8,7)这个点的回溯次数更是高达5000多,但是从理论上棋盘应该是对称的。
显然这个回溯次数极高的情况应该是本代码的一个bug,希望读者可以帮忙指正,未完待续~
问题规模的推广
显然规模为8还只是一种较为简单的情形。本代码测试时发现规模小于12时可以较快的得到一个哈密顿解。若不要求重新回到起点的话,规模最大可达60。这也是以后需要优化的地方。
因为目前使用的贪心算法主要通过优化边缘路径来提高搜索效率,当矩阵维数过高时中间的点的优先权值都将等于8,贪心也就失去了意义,故而可以通过分块处理采用分治的方法来处理,未完待续~
完整代码请见下载中心或Github
基于贪心算法的马踏棋盘哈密顿回路问题相关推荐
- 用贪心算法解决马踏棋盘问题
用贪心算法解决马踏棋盘问题 参考文章: (1)用贪心算法解决马踏棋盘问题 (2)https://www.cnblogs.com/Allen-win/p/7095293.html 备忘一下.
- 残缺棋盘问题算法分析_javascript使用递归回溯算法和贪心算法解决马踏棋盘问题...
马踏棋盘算法介绍和游戏演示 1.马踏棋盘算法也被称为骑士周游问题 2.将马随机放在国际象棋的8×8棋盘Board[0-7][0-7]的某个方格中,马按走棋规则(马走日字)进行移动.要求每个方格只进入一 ...
- java 马踏棋盘优化_我所知道的十大常用算法之马踏棋盘算法(深度搜索、贪心思想优化 )...
前言需求 今天我们学习的是马踏棋盘算法,我们还是从一个场景里引入看看 马踏棋盘算法也被称为骑士周游问题 将马随机放在国际象棋的6×6棋盘Board0-5的某个方格中 提示:马按走棋规则(马走日字)进行 ...
- 【算法】马踏棋盘算法 骑士走周游算法
文章目录 1.概述 2.贪心优化 1.概述 马踏棋盘算法和八皇后问题很相似:[算法]八皇后问题 骑士周游问题的解决步骤和思路 创建棋盘chessBoard,是一个二维数组 将当前位置设置为已经访问,然 ...
- 数据结构与算法|马踏棋盘算法(小甲鱼)C语言代码的算法分析
马踏棋盘算法(骑士周游问题)的算法分析 C语言代码部分来自小甲鱼的<数据结构与算法> 文章目录 马踏棋盘算法(骑士周游问题)的算法分析 一.C语言代码实现 二.代码分析与算法思路 题目要求 ...
- 【数据结构与算法】马踏棋盘(骑士周游世界)算法
一,基本介绍 1)马踏棋盘算法也称为骑士周游问题 2)将马随机放在国际象棋的8 × 8棋盘Board[0~7] [0~7]的某个方格中,马按走棋规则(马走日字)进行移动.要求每个方格只进入一次,走遍棋 ...
- 基于Java Swing 的马踏棋盘小游戏(附源码!免费下载!)
马踏棋盘游戏小项目 设计主要功能 运用的数据结构 运行流程讲解及录像 项目分类截图及源码链接! 设计主要功能 (1)设计内容:设计一个马踏棋盘游戏,马作为棋子,以马走日字的走法,将整个棋盘一次性走完, ...
- 数据结构(七)——Dijkasta 、Flyod、马踏棋盘算法
Dijkstra 算法 应用场景-最短路径问题 有 7 个村庄(A, B, C, D, E, F, G) ,现在有六个邮差,从 G 点出发,需要分别把邮件分别送到A, B, C , D, E, F 六 ...
- 骑士周游(马踏棋盘)问题
1,马踏棋盘算法介绍 马踏棋盘问题也被称为骑士周游问题 将马随机放在国际象棋的8*8的棋盘中的某个格子里,马按照走棋规则(日子)进行移动.要求每个方格只进入一次,走遍64个方格 2,马踏棋盘算法思路分 ...
最新文章
- 怎样修改Ubuntu的root帐户密码并使用root登录
- mPaas 厂商 push 不通排查指南
- 昨天是欧洲男人的,今天却属于亚洲女人
- xftp6设置默认打开文件的程序_修改文件默认打开方式,不改变原图标
- 简单的遮罩层加登录窗效果
- Spring Boot实战:数据库操作
- echarts 柱状图 ,颜色和显示设置
- 常用的表单正则表达式
- html 空行_一篇文章学习html「经典案例」
- 【NOIP2013】【Luogu1983】车站分级(建图,拓扑排序)
- MySQL 主外键关系
- 加快pip下载的速度---镜像
- android 手机设备刷新dns
- linux crontab测试,crontab使用测试
- 修改 Mixamo 导出的动画名字
- 一犯人在执行死刑前三天供出祖传治癌奇方
- iOS——JSONModel数据解析
- 幸福温馨抑或婚姻枷锁——戴尔与EMC的蜜月期究竟进展如何?
- J-LINK突然不能下载(错误:JLink Warning: RESET (pin 15) high, but should be low. Please check target)
- JS 音效触发器 / 给动画添加音效