• Windy数--数位dp


    题目链接:

    信息学奥赛一本通T1587-Windy 数 - C语言网

    题意:

    Windy 数:不含前导零且相邻两个数字之差至少为 2 的正整数被称为 Windy 数。

    在 A 和 B 之间,包括 A 和 B,总共有多少个 Windy 数?

    代码:

    1. #include <bits/stdc++.h>
    2. using namespace std;
    3. int nums[20];
    4. int dp[20][10];
    5. /*dp[i][j] 当前数字为第i位,前一位数字为j
    6. 满足不含前导0且相邻两个数差大于等于2的数的个数
    7. */
    8. int dfs(int pos,int pre,bool lead,bool lim){
    9. if(pos<0)
    10. return 1;
    11. if(!lim&&!lead&&dp[pos][pre]!=-1)
    12. return dp[pos][pre];
    13. int end=(lim?nums[pos]:9);
    14. int res=0;
    15. for(int i=0;i<=end;i++){
    16. if(lead){
    17. if(i==0)
    18. res+=dfs(pos-1,0,true,lim&&(end==i));
    19. else
    20. res+=dfs(pos-1,i,false,lim&&(end==i));
    21. }
    22. else{
    23. if(abs(i-pre)>=2)
    24. res+=dfs(pos-1,i,false,lim&&(end==i));
    25. }
    26. }
    27. if(!lim&&!lead)
    28. dp[pos][pre]=res;
    29. return res;
    30. }
    31. int solve(int x){
    32. int cnt=0;
    33. while(x){
    34. nums[cnt++]=x%10;
    35. x=x/10;
    36. }
    37. int res=dfs(cnt-1,0,true,true);
    38. }
    39. int main(){
    40. memset(dp,-1,sizeof(dp));
    41. int a,b;
    42. scanf("%d%d",&a,&b);
    43. int ans=solve(b)-solve(a-1);
    44. printf("%d\n",ans);
    45. }

    求两个数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]的,两者相减就得到答案。

  • 相关阅读:
    Postman接口测试流程
    机器如何快速学习数据采集
    ASP.NET Core 6.0 启动方式
    代码随想录算法训练营第七天|二叉树(截止到层序遍历)
    element ui el-select修改样式
    word图片无法居中,原因可能是非嵌入式!
    Redis(三) Redis的java客户端
    rsa加密解密java和C#互通
    选择适合的防火墙需要考虑哪些因素?
    Spring相关概念
  • 原文地址:https://blog.csdn.net/weixin_45772744/article/details/125339977