搜索题,关键在于优化常数和剪枝。
优化常数#
某一行、列、九宫格的“可填”状态使用一个九位二进制数维护(这一步大部分人能想到),然后三个数按位与得到某个格子实际“可填”的状态。紧接着,不要忙着用 for 循环遍历每一位,而应使用 lowbit 逐次取最低位,并通过事先维护的 log2[] 数组得到对应位数。这一步可以显著降低常数。
剪枝#
搜索顺序优化#
先搜索层数较浅、子树较少的分支,在本题中就是优先选择可填数字种类最少的格子。建议不要使用优先队列,而是每次遍历一遍棋盘(总共 ,十分少)暴力找到最小的,这样更快。
对于装箱问题如P10483 小猫爬山 ↗,也应当优先搜索大猫,因为这样的分支可能状态更少,可以快速得到一个较小的答案上界。
可行性剪枝#
当前某个格子无解时,立即放弃这条分支。
最优性剪枝#
该题需要且只需要求出一个解,不涉及最优性。然而,对于P10483 小猫爬山 ↗和P1731 生日蛋糕 ↗,当目前解已经必然不比已求出的解更优时,立即放弃该分支。这类剪枝的难点往往在于如何高效、充分、提前判定当前状态是否已经不优。