• BNU52325-Increasing or Decreasing-数位DP-DFS


    题目地址:  https://www.bnuoj.com/v3/problem_show.php?pid=52325

    两份代码,解释在第二份代码里面

    第一份代码整理一下看着爽

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 long long  dp[20][11][3];
     6 int digit[20];
     7 int dfs(int len , int fore , int state , bool limit)
     8 {
     9     if (len == 0)
    10         return 1;
    11     if ( !limit && dp[len][fore][state] != -1 )
    12         return dp[len][fore][state];
    13     int res = 0;
    14     int limitD = limit ? digit[len] : 9 ;
    15     for (int j = 0 ; j<=limitD; j++)
    16     {
    17         int i;
    18         if (fore == 10 && j == 0) i = 10;
    19         else i = j;
    20         if ( state == 0 ){
    21             if ( fore == 10 || i == fore )
    22                 res += dfs( len - 1 , i , 0 , limit && i == limitD );
    23         }
    24         else if ( state == 1 ){
    25             if ( fore == 10 || i <= fore )
    26                 res += dfs( len - 1 , i , 1 , limit && i == limitD );
    27         }
    28         else{
    29             if ( fore == 10 || i >= fore )
    30                 res += dfs( len - 1 , i , 2 , limit && i == limitD );
    31         }
    32     }
    33     if (!limit)
    34         dp[len][fore][state] = res;
    35     return res;
    36 }
    37 long long solve(long long x)
    38 {
    39     int cnt = 0;
    40     while (x)
    41     {
    42        digit[ ++cnt ] = ( int )( x % 10LL );
    43        x /= 10LL;
    44     }
    45     return dfs( cnt , 10 , 1 , true ) + dfs( cnt , 10 , 2 , true ) - dfs( cnt , 10 , 0 , true );
    46 }
    47 int main()
    48 {
    49     memset(dp,-1,sizeof dp);
    50     int N;
    51     scanf("%d", &N );
    52     long long  a,b;
    53     while (N--)
    54     {
    55         scanf("%lld %lld" , &a , &b );
    56         printf("%lld
    ", solve( b ) - solve ( a - 1LL ) );
    57     }
    58 }
    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 //dp[i][j][k] 长度为i,前一位j,状态为k
     6 //k=0 相等 k=1 递增 k=2 递减
     7 long long  dp[20][11][3];
     8 int digit[20];
     9 //dfs计算在digit限制下,长度为len,前一位为fore,的state状态的数字,特别的令fore==10代表前面全是0
    10 int dfs(int len , int fore , int state , bool limit)
    11 {
    12     //最边界计数,即枚举到最后一位,0即为全是前导0。
    13     if (len == 0)
    14     {
    15         return 1;
    16     }
    17     //记忆化搜索
    18     if (!limit && dp[len][fore][state] != -1)
    19      return dp[len][fore][state];
    20     int res = 0;
    21     int limitD = limit?digit[len]:9;
    22     for (int j = 0 ; j<=limitD; j++)
    23     {
    24         int i;
    25         //确定填写的0,前导0变10,真0还是0
    26         if (fore == 10 && j == 0) i = 10;
    27         else i = j;
    28         //如果前导0或者满足要求,那么继续dfs
    29         //其中有些判断可以省略,但是所有的都加上fore==10,便于理解
    30         if (state==0)      //相等
    31         {
    32                     if (fore==10||i==fore)
    33                     res += dfs(len-1,i,0,limit&&i==limitD);
    34         }
    35         else if (state==1)//递减
    36         {
    37                     if (fore==10||i<=fore)
    38                     res += dfs(len-1,i,1,limit&&i==limitD);
    39          }
    40          else           //递增
    41          {
    42                     if (fore==10||i>=fore)
    43                     res += dfs(len-1,i,2,limit&&i==limitD);
    44          }
    45     }
    46     if (!limit) dp[len][fore][state] = res;
    47     return res;
    48 }
    49 long long solve(long long x)
    50 {
    51     int cnt = 0;
    52     while (x)
    53     {
    54        digit[++cnt] = (int)(x % 10LL);
    55        x /= 10LL;
    56     }
    57     //递增+递减-相等
    58     return dfs(cnt,10,1,true) + dfs(cnt,10,2,true) - dfs(cnt,10,0,true);
    59 }
    60 int main()
    61 {
    62     memset(dp,-1,sizeof dp);
    63     int N;
    64     scanf("%d",&N);
    65     long long  a,b;
    66     while (N--)
    67     {
    68         scanf("%lld%lld",&a,&b);
    69         printf("%lld
    ",solve(b) - solve(a-1LL) );
    70     }
    71 }
  • 相关阅读:
    论文笔记4
    论文笔记3
    论文笔记2
    论文笔记1
    论文笔记
    AFG与AWG的比较
    Linux下“有线线缆被拔出”问题的解决
    python生成excel格式座位表
    PythonTip--一马当先--bfs
    python pygame--倒计时
  • 原文地址:https://www.cnblogs.com/HITLJR/p/5965820.html
Copyright © 2020-2023  润新知