随笔17.10.26

来源:互联网 发布:免费越狱软件 编辑:程序博客网 时间:2024/06/07 05:21

这两天继续看了一下数位dp的内容

数位dp一般用于求出在给定区间[A,B]内,符合条件的数的个数,条件一般是与数的组成有关(例如,不出现连续的1,不出现4.......)


举例说明,如果我们要求[0,321]之间的个数,最基本的方法就是暴力枚举,但是运行太慢,所以用数位dp。

我们现将321拆成一个数组,分别是个十百位,然后先对百位进行枚举,百位枚举1时,个位百位都可以0~9,但是如果百位为3,那么百位只能选0,1,2

很明显可以看出枚举的内容有一个限制,但不是对每一次枚举的都有限制。百位为1时不管后面数字为什么都不会有错误,但是百位为3就不行。

这个可以看做是一个上限了;

还有一个就是百位为0  十位为0的情况,成为前导零,这个对于有的题目是有影响的,可以看做是一个下限,不过并不是所有题目都需要这个。看具体要求吧。


数位dp里面的bfs部分一般情况如下:

int dfs(int pos,bool limit,bool lead)//pos为数位个数,limit判断上限,有的题目需要前导零lead,具体在改写一下判断条件

{

if(pos==-1)return 1;

if(!limit && dp[pos][state]!=-1) return dp[pos][state];  

   /*在没有限制的条件记忆化,这里与下面记录状态是对应*/  
    int up=limit?a[pos]:9;
    ll ans=0;   //开始计数  
    for(int i=0;i<=up;i++)
    {  
        if() ...  //添加具体的判断条件
        else if()...  
        ans+=dfs(pos-1,/*状态转移*/,lead && i==0,limit && i==a[pos]) 
        当前数位枚举的数是i,然后根据题目的约束条件分类讨论 
        去计算不同情况下的个数,还有要根据state变量来保证i的合法性,这里一
         定要保存枚举的这个数是合法*/  
    }   
    if(!limit && !lead) dp[pos][state]=ans;  
    return ans;  
 具体的题目还需要变一下


原创粉丝点击