题目链接:
题意:
Windy 数:不含前导零且相邻两个数字之差至少为 2 的正整数被称为 Windy 数。
在 A 和 B 之间,包括 A 和 B,总共有多少个 Windy 数?
代码:
#include <bits/stdc++.h>
using namespace std;
int nums[20];
int dp[20][10];
/*dp[i][j] 当前数字为第i位,前一位数字为j
满足不含前导0且相邻两个数差大于等于2的数的个数
*/
int dfs(int pos,int pre,bool lead,bool lim){
if(pos<0)
return 1;
if(!lim&&!lead&&dp[pos][pre]!=-1)
return dp[pos][pre];
int end=(lim?nums[pos]:9);
int res=0;
for(int i=0;i<=end;i++){
if(lead){
if(i==0)
res+=dfs(pos-1,0,true,lim&&(end==i));
else
res+=dfs(pos-1,i,false,lim&&(end==i));
}
else{
if(abs(i-pre)>=2)
res+=dfs(pos-1,i,false,lim&&(end==i));
}
}
if(!lim&&!lead)
dp[pos][pre]=res;
return res;
}
int solve(int x){
int cnt=0;
while(x){
nums[cnt++]=x%10;
x=x/10;
}
int res=dfs(cnt-1,0,true,true);
}
int main(){
memset(dp,-1,sizeof(dp));
int a,b;
scanf("%d%d",&a,&b);
int ans=solve(b)-solve(a-1);
printf("%d\n",ans);
}
求两个数a和b之间数位满足某种关系的数的个数
步骤:
1.确定dp[i][j]的含义,编写dfs函数
dfs函数中:
1)返回条件
2)当不为特殊条件(如题中!lim-非右树,!lead-非前导零),且dp[i][j]不为初始值,直接返回dp[i][j]
3) 否则说明当前形参对应的值需要计算
若该位的lim为true(说明该数位的是最右链上的点,当前pos能取到的最大数就是nums[pos],否则能去到最大值),之后用for循环从0-end枚举每一位可能的值,计算res
4)当不为特殊条件,直接令dp[i][j]=res,下次就无需再计算
5)返回res
2.对数b,将各数位进行分解保存到nums数组中(具体怎么分解根据题意要求)
调用dfs计算[1,b]满足条件的数的个数,同理计算[1,a-1]的,两者相减就得到答案。