NOIP2018 填数游戏 搜索、DP
感觉这个题十分好玩于是诈尸更博。一年之前的做题心得只有这道题还记得清楚……
设输入为$n,m$时的答案为$f(n,m)$,首先$f(n,m)=f(m,n)$所以接下来默认$n \leq m$。一件重要的事情是打表得到当$m>n+1$时$f(n,m) = f(n,m-1)*3$,证明不会。
所以最后的问题是快速得到$f(8,9)$。$n,m$不大考虑搜索。
首先考虑一些没用的剪枝:
1、同一条对角线上填入的数字自底向上不增。这个不难反证得到。
2、如果存在$(i,j)\(和\)(i+1,j-1)\(填入的数字相同,那么\)(i+1,j)\(与\)(n,m)$构成的矩形中一条对角线上所有位置的值必须相同。也可以反证得到。
我们假设用了这些剪枝可以剪掉绝大部分状态,那么我们考虑如何check一个通过上述剪枝得到的答案是否合法。暴力的复杂度是$15 \times \binom{15}{8}$难以接受,我们考虑一些不同的思路。
对于两条路径$P,Q$,找到第一次分岔的位置,记做$(x,y)$,那么这两条路径中必定一条向右走、一条向下走。不失一般性地假设$P$向右走,那么$P$得到的二进制串必须比$Q$得到的二进制串小。而$(x,y)$是第一次分岔的位置,所以$P,Q$是否满足条件和$(x+1,y)\(以及\)(x,y+1)\(作为起点的所有路径的串的\)\min$和$\max$有关。如果能够得到从某个点开始到达终点的所有串的$\min$和$\max$,判断合法就迎刃而解了。
对于求以任意位置作为起点到达终点的串的$\min$和$\max$,考虑DP:设$f_{i,j,0/1}\(表示从\)(i,j)\(到\)(n,m)\(的所有串的字典序\)\min / \max$,转移枚举下一步去到哪里。注意到DP的复杂度是$O(nm)$的,相比之前有很大的提升。
这样有可能还是跑不进$2s$,但是注意到下面check合法则上面所有的剪枝都一定满足。如果可以最大化check方式在搜索中的剪枝效果,就可以更快速地搜出结果。
那么可以这样做:按照对角线倒着填数,每一次填入一个位置之后立即计算它的DP值,判断能够判断是否合法的位置,如果某些位置作为第一次分岔的位置已经不合法,则不往下搜。不难发现这样的搜索剪枝是包含了上面的剪枝1、2的,是一个更强的剪枝。这样你就可以在LOJ上以$200ms$的速度搜出$f(8,9)$,问题就完成了。