Python实现A*算法的十五数码

参考以下博客实现15数码

https://blog.csdn.net/qq_35976351/article/details/82767029

发现其时间和节点复杂度为:

未修改的时间复杂度和节点数​​​

 然后发现其代码中计算节点数量是不合理的

计数不合理

 如上图第12行所示:它是在判重前对节点计数。因为如果重复了,我们并没有把该状态再次加到哈希表和堆中,所以不应该再次计算一次。应该把第SUM_NODE_NUM+=1放在hash_set.add(h)后面或者前面。修改后结果为:

修改计数位置之后

 发现数量确实少了不少。继续阅读发现其hn并没有真正的发挥启发式函数的作用:

第8行有问题

 此时的hn是按照其父节点状态和目标节点状态所计算的,这就意味着其所产生的所有子节点fn都和其父节点相同。所以产生的所有子节点的fn都是相等的(因为gn都是父节点加1和hn都是父节点状态与目标节点状态的距离)。所以要让hn是其当前节点状态与目标节点状态的距离,即state和end_node.state的距离,故修改manhattan_dis()函数为:

把cur_state=cur_node.state和end_state=end_node.state那两行注释掉 ,函数传入参数改为cur_state和end_state

在调用该函数(即上上图的第八行代码)的时候参数传递改为以下

 hn = dis_fn(state, end_node.state)  # 启发的距离函数

然后其结果为:

这样我们就发现不仅节点大大的减少,而且时间也少了0.1s左右。所以修改完成。

总结:此博客是在上述博客源码的基础上修改的,可复制其代码,然后按照这个步骤修改就行。这一次真正体会到代码的位置和启发式函数到底有多大的差别,代码路还很长,不忘初心,继续前行。

附测试用例:

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
A*算法是一种启发式搜索算法,可以用来十五数码问题十五数码问题是一种经典的滑块拼图游戏,其中有一个4x4的网格,上面有编号为1到15的方块,还有一个空方块。目标是通过交换方块,将它们按照从1到15的顺序排列好,最后是一个完全有序的网格。 A*算法的基本思想是将问题抽象为一个图,其中每个节点代表一个局面状态,边表示状态之间的转移。我们使用一个启发函数来评估每个节点的优先级,这个函数考虑到从当前状态到目标状态的距离估计。在十五数码问题中,可以使用曼哈顿距离来评估启发函数,即从当前状态到目标状态所需要的最小水平和垂直移动次数之和。 具体实现A*算法十五数码问题的步骤如下: 1. 创建一个优先队列,用于存储待扩展的节点。 2. 将初始状态加入优先队列。 3. 从优先队列中选择优先级最高的节点进行扩展。 4. 生成所有可达的下一状态,并计算每个状态的优先级。 5. 将未扩展的状态加入优先队列。 6. 重复步骤3和4,直到找到目标状态。 在Python实现A*算法十五数码问题可以借助以下数据结构和算法: 1. 使用优先队列来存储待扩展的节点,可以使用heapq库实现。 2. 设计一个状态类来表示每个局面状态,包括当前状态、父节点、移动代价、优先级等信息。 3. 利用哈希表来记录已经生成的状态,以避免重复扩展。 4. 实现曼哈顿距离的计算函数来评估每个状态的优先级。 总结来说,借助A*算法的思想和Python的数据结构和算法库,可以较为高效地十五数码问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值