Description
在一个 $5 \times 5$ 的棋盘上有白色和黑色的骑士各 $12$ 个,以及一个空位(每个骑士都可以移动到和它横坐标相差 $2$,纵坐标相差 $1$ 或横坐标相差 $1$,纵坐标相差 $2$ 的空位上)。给定初始棋盘,求出至少移动多少次能得到目标棋盘(如下图)。如果 $15$ 步以内不能得到,输出 $-1$ 。
Source
Solution
IDA* 经典题。
不管是 A* 还是 IDA*,最重要的就是 估价函数,定义为:
其中 $f(n)$ 是节点 $n$ 的估价函数,$g(n)$ 是当前的实际步数,$h(n)$ 是对未来步数的最完美估价。
为什么是这样呢?
假设你觉得到 $n$ 这个状态需要 $f(n)$ 步,你到当前状态已经花了 $g(n)$ 步,现在你想从当前状态到 $n$ 这个状态,在运气最好的情况下还需要 $h(n)$ 步。若 $g(n) + h(n) > f(n)$,则显然当前状态不能再 $f(n)$ 步之内到达 $n$ 这个状态。
如果要让所有马归位,状态数会非常多,所以我们考虑移动空位,即让空位与马交换位置,直到当前状态与目标状态相同。除此之外,这道题有要求 $15$ 步之内完成,所以可以 迭代加深,即规定最大深度,超过这个深度就直接退出。换句话说,我们可以把这个最大深度作为 $f(n)$ 。
本题中的 最完美估价:
1 | const int goal[MAXN + 1][MAXN + 1] = { //目标矩阵 |
对于一匹不在自己位置上的马,在最优的情况下,我们只需要一次移动就能使这匹马归位。假设每一匹这样的马都需要移动一次,所以我们统计这样的马的个数即可。
还有一个剪枝,就是记录上一步是空格在哪个位置,下一步再跳回上一步的位置显然不优,这样可以少掉很多无用递归。
Code
1 |
|