• HDU 2089 不要62 数位DP


    预处理+递推

    #include <iostream>
    using namespace std  ;
    int f[8][10] ;//f[i][j]表示第i位是数j时符合条件的数字数量 
    int digit[9] ;//digit[i]表示n从右到左第i位是多少 
    void Init()
    {
        f[0][0]=1 ;
        for(int i=1 ;i<=7 ;i++)
        {
            for(int j=0 ;j<10 ;j++)//枚举第i位 
            {
                for(int k=0 ;k<10 ;k++)//枚举第i-1位
                {
                    if(!(j==6 && k==2) && j!=4)//如果符合条件
                        f[i][j]+=f[i-1][k] ; 
                } 
            }
        }
    }
    int callen(int n)//计算n的长度 
    {
        int cnt=0 ;
        while(n)
        {
            cnt++ ;
            n/=10 ;
        }
        return cnt ;
    } 
    void caldigit(int n,int len)//计算n的digit数组 
    {
        memset(digit,0,sizeof(digit)) ;
        for(int i=1 ;i<=len ;i++)
        {
            digit[i]=n%10 ;
            n/=10 ;
        }
    }
    int solve(int n)//计算[0,n]区间满足条件的数字个数 
    {
        int ans=0 ;
        int len=callen(n) ;
        caldigit(n,len) ;
        for(int i=len ;i>=1 ;i--)
        {
            for(int j=0 ;j<digit[i] ;j++)//枚举第i位取值 
            {
                if(!(j==2 && digit[i+1]==6) && j!=4)//第i位满足条件 
                    ans+=f[i][j] ;
            }
            if(digit[i]==4 || (digit[i]==2 && digit[i+1]==6))//第i位已经不满足条件,则i位以后都不可能满足条件,结束循环 
                break ;
        }
        return ans ; 
    }
    int main()
    {
        Init() ;
        int n,m ;
        while(~scanf("%d%d",&n,&m))
        {
            if(n==0 && m==0)
                break ;
            printf("%d
    ",solve(m+1)-solve(n)) ;//用[0,m]-[0,n)即可得到区间[n,m] 
        }
        return 0 ;
    }

    记忆化搜索

    #include <iostream>
    using namespace std ;
    int f[8][2] ;//dp[i][0]:前i位符合要求 dp[i][1]:前i位符合要求且i+1位是6
    int digit[9] ;//digit[i]表示n从右到左第i位是多少 
    int dfs(int i,int s,bool e)//i表示当前位,s表示i位之前的状态,e表示当前位是否可以随意填写 
    { 
        if(i==0)
            return 1 ;
        if(!e && f[i][s]!=-1)
            return f[i][s] ;
        int res=0 ;
        int u=e?digit[i]:9 ;
        for(int d=0 ;d<=u ;d++)
        {
            if(d==4 || (s && d==2))
                continue ;
            res+=dfs(i-1,d==6,e&&d==u) ;
        }
        return e?res:f[i][s]=res ;
    }
    int callen(int n)//计算n的长度 
    {
        int cnt=0 ;
        while(n)
        {
            cnt++ ;
            n/=10 ;
        }
        return cnt ;
    }
    void caldigit(int n,int len)//计算n的digit数组 
    {
        memset(digit,0,sizeof(digit)) ;
        for(int i=1 ;i<=len ;i++)
        {
            digit[i]=n%10 ;
            n/=10 ;
        }
    }
    int solve(int n)//计算[0,n]区间满足条件的数字个数 
    {
        int len=callen(n) ;
        caldigit(n,len) ;
        dfs(len,0,1) ;
    }
    int main()
    {
        int n,m ;
        memset(f,-1,sizeof(f)) ;
        while(~scanf("%d%d",&n,&m))
        {
            if(n==0 && m==0)
                break ;
            printf("%d
    ",solve(m)-solve(n-1)) ;//用[0,m]-[0,n)即可得到区间[n,m]
        }
        return 0 ;
    }

     记忆化搜索 V2

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    using namespace std;
    typedef long long ll;
    int a[20];
    int dp[20][2];
    int dfs(int pos,int pre,int sta,bool limit)
    {
        if(pos==-1) return 1;
        if(!limit && dp[pos][sta]!=-1) return dp[pos][sta];
        int up=limit ? a[pos] : 9;
        int tmp=0;
        for(int i=0;i<=up;i++)
        {
            if(pre==6 && i==2)continue;
            if(i==4) continue;//都是保证枚举合法性
            tmp+=dfs(pos-1,i,i==6,limit && i==a[pos]);
        }
        if(!limit) dp[pos][sta]=tmp;
        return tmp;
    }
    int solve(int x)
    {
        int pos=0;
        while(x)
        {
            a[pos++]=x%10;
            x/=10;
        }
        return dfs(pos-1,-1,0,true);
    }
    int main()
    {
        int le,ri;
        //memset(dp,-1,sizeof dp);可优化
        while(~scanf("%d%d",&le,&ri) && le+ri)
        {
            memset(dp,-1,sizeof dp);
            printf("%d
    ",solve(ri)-solve(le-1));
        }
        return 0;
    }
  • 相关阅读:
    Storyboard中segue使用总结
    Present ViewController Modally
    UILabel设置富文本格式显示
    objective-c 中随机数的用法 (3种:arc4random() 、random()、CCRANDOM_0_1() )
    ios中static的作用
    NSBundle的使用,注意mainBundle和Custom Bundle的区别
    OC的基础语法OC继承和复合语言特性目标动作回调
    动态规划-被3整除的子序列
    A
    Coins POJ
  • 原文地址:https://www.cnblogs.com/Aragaki/p/7524104.html
Copyright © 2020-2023  润新知