ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

马周游(马走棋盘)及剪枝分析

2019-09-23 21:00:38  阅读:334  来源: 互联网

标签:剪枝 周游 棋盘 int System pace 马走 now public


一、题目

在n x n棋盘(有n x n个格点的棋盘)的某个格点上有一个中国象棋马,马走日字。

求一条周游棋盘的路径,使得马能够从起始位置起沿着该路径每个格点恰好走一次最后回到出发位置。

 

二、思路

1、初期思路:

  首先想到的是用DFS来解决,不仅可以遍历全局还可以回溯,于是着手做了起来,虽然是DFS,但是在此题中,不需要用到邻接矩阵,也不需要数组来判断每点是否到过,一开始的设想是利用二维数组当成棋盘,默认为全0,初始点是1,第二步就是2,这样一直走下去,直到走满,每次需要判断八个方向,如果该往该方向走后仍在棋盘中,就接着判断下一步的方向,直到八个方向都走过了或棋盘已经走满,就返回上一步棋。

2、回溯的方法:

  程序使用递归思想,每一步都会创建一个优先队列,在未完成算法的前提下,只要优先队列不为空,就会一直执行下去。

 

3、遇到问题:

但在实际解决过程中,每次递归需要传入当前棋盘数组,但返回之前步数时数组老是会被更改,所以就尝试了用字典来保存每步棋,奇怪的是每次操作都会改变所有字典中的值,使得实验出错,改用三维数组后也遇到了同样的问题。

 

浅拷贝和深拷贝问题:

这两种复制和clone函数都出现了相同的问题,在百度后了解到这涉及了浅拷贝和深拷贝,浅拷贝过程中只是引用了数组的地址(实际指向同一个空间),深拷贝才是真正开辟了新的空间

解决方法:为了避免麻烦就直接自己用两个for循环来复制数组,运行,得到正常的结果。

 

还有一个是用java自带函数时,上图最后一条复制语句会对所有二维数组赋值而不是当前二维数组,在室友电脑上试过后也是一样。(未解决)

三、剪枝

有了之前的思路,虽然能够解决问题,但还是远远不够的,在棋盘为8*8时几乎跑不出答案,我们需要思考剪枝方案使代码更快运行。

由于涉及到特定问题的剪枝需要对问题做细致研究,所以就直接百度了剪枝的方案如下:

 

根据剪枝方案来改造自己的代码:

1、 为了计算每个位置的可走方向数,我们需要添加一个方法来判断某个位置有几种走法,只需要对当前点进行八个方向的遍历即可,难点是优先选择可走步数少的点,一开始我每次都走最优点,但发现这样无法走到终点,且无法再回溯,所以我们是需要将每一步的所有可走点的可走步数保存起来的,这样在走错时才可能进行回溯,这里用到了优先队列这个结构。

 

 

 使用优先队列免去了自己去写创建数组和需要的排序算法,我们只需要给优先队列制定排列规则即可,而无需搞懂其内部的具体实现。这带来了很大的便利。

 

2、 添加一个方法来计算某个位置到中心的距离,然后在优先队列中加入距离的比较即可实现剪枝2。

3、  最终实现的动态图

标签:剪枝,周游,棋盘,int,System,pace,马走,now,public
来源: https://www.cnblogs.com/Unicron/p/11574784.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有