数位dp

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数位dp相关的知识,希望对你有一定的参考价值。

BZOJ 1026 Windy数

  题意:

    给你两个数l,r,求[l,r]中不含前导零且相邻两个数字之差至少为2的正整数个数。

  题解:

    首先很容易想到dfs(x,pre,lim),pre表示的是前一位的数字。但是如果这样就会有一个问题,举个例子,如果r=1000,对于数字15,它本身是符合要求的,但在dp中,它被看作了0015,这样的话前2位的差为0,就被当作不符合要求的数排除掉了。为了解决这个问题,我们在dp是再加入一个状态led,表示比当前位高的几位是不是全都是前导0,而在转移时,如果led为1,就不用排除差小于2的情况了。

    接下来给出代码:

#include<cstdio>
#include<cstring>
int f[15][10],a[15],cnt;
int abs(int x){return x<0?-x:x;}
int dfs(int x,int pre,bool led,bool lim){
    if(x==0) return 1;
    if(!led&&!lim&&f[x][pre]!=-1) return f[x][pre];
    int ans=0,maxl=lim?a[x]:9;
    for(int i=0;i<=maxl;++i) if(led||(!led&&abs(i-pre)>=2))
        ans+=dfs(x-1,i,led&&!i,lim&&i==maxl);
    if(!led&&!lim) f[x][pre]=ans; return ans;
}
int solve(int x){
    for(cnt=0;x;x/=10) a[++cnt]=x%10;
    return dfs(cnt,0,1,1);
}
int main(){
    memset(f,-1,sizeof f); int a,b; scanf("%d%d",&a,&b);
    printf("%d",solve(b)-solve(a-1)); return 0;
}

 

以上是关于数位dp的主要内容,如果未能解决你的问题,请参考以下文章

数位dp小练

动态规划_计数类dp_数位统计dp_状态压缩dp_树形dp_记忆化搜索

数位DP

数位dp

HDU 2089 数位dp入门

数位DP