你没看错又是关于IDA*的题目,那是因为我正在刷刘老师的例题和习题。。。
这次的IDA*也是非常具有标志性的题,确实以后碰到这种状态空间搜索IDA*是一个非常不错的选择。
题目
传送门:https://vjudge.net/problem/UVA-1343
有个#字型的棋盘,2行2列,一共24个格,每个格子上都有一个数字(1或2或3),如下图:
我们可以往A,B,C,D,E,F,G,H八个方向拉动,每次拉动会把离那个字母最靠近的数字移到最远处,然后其他数字会靠近那个字母一位(其实就相当与滚动一样)。现在的目标是找到最短的步数使得中间8个位置的数字相同(要么同时为1,要么同时为2,要么同时为3),如果相同步数有多种情况,则输出字典序最小的那种。
首先我们会想到八数码问题,的确挺像,但是问题在于八数码的情况并没有这个多,如果我们做的操作为x,那我们所得到的情况就为8的x次方,这就非常可怕了,所以这题用BFS做必须要有非常优秀的剪枝。刘老师在书上所写BFS的方法是将1,2,3分开讨论,比如说讨论1的时候将2,3看成同样的数字,这样可以减少枚举情况。
但是,这题并不建议使用BFS,因为非常麻烦,再者,IDA*在解决状态空间问题上可是一个好工具。昨天我们着重介绍了A*算法的g(n)函数和h(n)函数,由于g(n)函数就是深度,所以,我们只需要找到h(n)就能搞定这个问题。
我们可以这样思考,假设每一次我们的移动可以多增加一个相同的数字,那么如果我们最大移动步数(最大深度)减去现在的移动步数无法大于现在仍然所需的相同数字,那我们就可以直接跳出了,所以,我们就得出了h(n)。核心的判断条件为:
d(当前步数)+h()(当前情况下得到答案仍需多少步) < maxn(最大步数)
所以,我们只需对最大步数maxn进行迭代即可
代码
1 |
|