我曾难自拔于世界之大 / 也沉溺于其中梦话 / 不做|

zhengtuodu

园龄:2个月粉丝:0关注:0

数位 DP 学习笔记

因为 ABC 考了一次,而且放在 C 题,所以特地来学习一下。

适用范围

数位 DP 的题目好像不太容易考,但是一旦考了数位 DP 就可以愉快地套板子了。

数位 DP 的题目一般长这个样子:
给定整数 LR,求:

i=LRf(i)

其中,f(i) 可以表示一个式子的取值,也可能是对于 i 这个数是否有一些特性的判断。
然后数据范围特别大,一般是 109 或者 1018 量级。

还是比较容易识别的。

解决问题

对于数位 DP,解决方式一般是套板子。

考虑将原式化为: i=1Rf(i)i=1L1f(i)

运用前缀和的思想就可以明白。

对于求 i=1Xf(i) 的问题,考虑用记忆化搜索来做。

考虑设置哪些状态。


pos

首先,我们既然需要一位一位地填数字,必然需要一个状态 pos 表示当前搜索到了第几位。

lst / sum

第二个状态根据题目来定。
如果题目是求数字各数位间关系,那么显然存上一个数位用的数字 lst
如果题目是求数字各数位的和之类的问题,那么就需要用一个 sum 来表示当前的总和。

limit

然后还需要一个状态来约束搜索的范围,将其称为 limit,意义为:“前面所有位有没有填满”。

为什么需要它?它有什么用?

考虑一个例子: 114514

在这个例子里面,打比方说,假如我们已经搜索到了这个位置:1145??

接下来 limit 就派上了用场。

现在前 4 位已经被填满了,填第 5 位的时候,limit 就等于 1

所以当前位需要收到 limit 的约束:这一位的搜索上界只能到 1,而不能到 9

现在显然了,如果没有 limit,那将会在 114514 的范围里搜出一个不符条件的 114524

lead

最后,肯定需要一个东西来判断前导 0

题目里一般都会说:不计入前导 0lead 的存在就是为了防止这种情况。

其中,lead=0 代表前导为 0lead=1 则表示无前导 0

有时,有无前导 0 的情况还需要分开计算。


接着开始搜索。

首先,如果我们已经搜完所有的数位,必然需要结束。此时即 pos=0
这时直接返回,如果求个数就是 1 个,求总和就是和为 sum

接着,记忆化搜索必然需要记忆。如果记忆过了,那么就可以结束了。

其中,limit=0lead=1 才能读取,如果不是这样,这个状态所形成的数就是不合法的,肯定是不能读取的。

第三步,寻找搜索上界。显然,如果前面搜完了即 limit=1,那么上界就是 X 的第 pos 位。否则上界为 9

下界显然是 0

对于每个数码,进行判断,如果满足条件才能继续搜下一位。

本文作者:zhengtuodu

本文链接:https://www.cnblogs.com/zhengtuodu/p/18674734

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   zhengtuodu  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起