参考以下博客实现15数码
https://blog.csdn.net/qq_35976351/article/details/82767029
发现其时间和节点复杂度为:
![](https://i-blog.csdnimg.cn/blog_migrate/e2749ec22dea462dd211a4b918d93ca5.png)
然后发现其代码中计算节点数量是不合理的
![](https://i-blog.csdnimg.cn/blog_migrate/a167cda8549a193c30cfc75089f4b996.png)
如上图第12行所示:它是在判重前对节点计数。因为如果重复了,我们并没有把该状态再次加到哈希表和堆中,所以不应该再次计算一次。应该把第SUM_NODE_NUM+=1放在hash_set.add(h)后面或者前面。修改后结果为:
![](https://i-blog.csdnimg.cn/blog_migrate/bfb06e9b5070eebd4691fd437779a84d.png)
发现数量确实少了不少。继续阅读发现其hn并没有真正的发挥启发式函数的作用:
![](https://i-blog.csdnimg.cn/blog_migrate/2a4fe339f639b0176ce1ea76c5a7408f.png)
此时的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左右。所以修改完成。
总结:此博客是在上述博客源码的基础上修改的,可复制其代码,然后按照这个步骤修改就行。这一次真正体会到代码的位置和启发式函数到底有多大的差别,代码路还很长,不忘初心,继续前行。
附测试用例: