题目链接:点击打开链接
//数位dp 记忆化搜索解法
#include<stdio.h>
#include<string.h>
#include<math.h>
int dp[15][10][2];//dp[i][j][k] i 表示数位 j 表示 第i为上的数 k表示有无前导零 1表有 0 表示没有
int digit[15];
int dfs(int pre,int first,int pos,int doing )//pre 前一位上的数值 first 前面是不是全是0 pos 当前枚举的位置 doing是否是上界
{
if(pos==-1)return 1;//枚举到最后一位都合法的话 这个数就合法
if(!doing && dp[pos][pre][first]!=-1)return dp[pos][pre][first];//记忆化
int End,i;
int ans=0;
End=doing?digit[pos]:9;
for(i=0;i<=End;i++)
{
if(first==1)//如果前面全是0 则当前位就是首位可以随便取值
{
if(i==0)ans+=dfs(0,1,pos-1,doing &&i==End );
else ans+=dfs(i,0,pos-1,doing && i==End);
}
else
{
if(fabs(i-pre)<2)continue;//如果当前位上的数 和前一位上的数相差小于2 continue
ans+=dfs(i,0,pos-1,doing && i==End);
}
}
if(!doing)
dp[pos][pre][first]=ans;
return ans;
}
int solve(int x)
{
int l;
l=0;
memset(digit,0,sizeof(digit));
memset(dp,-1,sizeof(dp));
while(x>0)
{
digit[l++]=x%10;
x=x/10;
}
return dfs(0,1,l-1,1);
}
int main()
{
int a,b;
while(scanf("%d %d",&a,&b)!=EOF)
{
printf("%d\n",solve(b)-solve(a-1));//包含两端所以 solve(b)-solve(a-1)
}
return 0;
}