数位dp的两种实现方式
一.递推
学的第一种方法就是这个,但是个人认为这种方式在某些题上比较难实现,比如:Blance Number(HDU-3709).这道题本蒟蒻没想出怎么用递推预处理,反而是记忆化搜索的方式更容易懂.
以HDU-2089为例,本题的递推还是比较好实现的.
代码
二.记忆化搜索
这种方法就比较烂大街了,基本每道数位dp题,网上的解题报告都是记忆化搜索实现.基本模板是:
LL dfs(int pos,int sta,bool limit,bool lead)
{
if(!pos) return st[sta];
if(!lead&&!limit&&f[pos][sta]!=-1) return f[pos][sta];
int len = limit?a[pos]:9;
LL res = 0;
for(int i=0;i<=len;i++)
{
if(lead&&!i) res+=dfs(pos-1,sta,limit&&i==len,lead);
else res+=dfs(pos-1,get(sta,i),limit&&i==len,lead&&i==0);
}
if(!limit&&!lead) f[pos][sta] = res;
return res;
}
需要说明的是什么时候才能记忆化,我们要保证下次搜索记忆化返回的方案数与上次搜索的状态相同才行.这里没有最高位限制且没有前导零才能记忆化.以POJ 3252为例子,如果我们有前导零也记忆化会导致前后状态不同返回错误的方案数.eg:(00) __ 在有前导零的情况下返回0000,0010两种方案(0001前三个都被算作前导零不计入).下次我们有最高位限制搜索10__时,会返回错误的方案数2.实际是1001的第三个0在没有前导零标记下是可以计入的.
题目还不是做了很多,以后再持续总结.