数位dp(2)

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;
}
原文地址:https://www.cnblogs.com/jxcakak/p/7468038.html