zoukankan      html  css  js  c++  java
  • HDU 3555 Bomb(数位DP)

    http://acm.hdu.edu.cn/showproblem.php?pid=3555

    题意:0-n之间有多少个数包含"13"的

    分析:dp[pos][have]

             pos代表当前的位置
             have0表示前面出现的数字里没有49
             have1表示前面结尾的位置是4
             have2表示前面出现的数字里有49了

    #include<string.h>
    #include<stdio.h>
    const int MN=100;
    #define LL long long
    LL dp[MN][10];//dp[i,j]i长度可以任意数的个数
    int digit[MN];
    LL n;
    
    //have0表示前面的没有49,have1表示已4结尾,have2表示前面包含了49
    LL DFS(int pos,int have,int doing)//pos表当前位置
    {
        if(pos==-1) return have==2;
        //表示后面长度可以任意数且已经搜索过
        if(!doing && dp[pos][have]!=-1) return dp[pos][have];
        int end=doing?digit[pos]:9;
        LL ans=0;
        for(int i=0; i<=end; i++)
        {
            int nhave=have;
            if(have==0 && i==4)
                nhave=1;
            if(have==1 && i==9)
                nhave=2;
            if(have==1 && i!=9)
                nhave=0;
            if(have==1 && i==4)//前面的数十4,如果当前的是4,这种情况别忘记
                nhave=1;
            ans+=DFS(pos-1,nhave,doing && i==end);
            //前面取到了最大数,后面的数不能任意取了
        }
        if(!doing)
        {//在pos以后为可以取任意数的情况下,这种状态是饱满的,做一个记忆储存,供后面查询使用
            dp[pos][have]=ans;
        }
        return ans;
    }
    
    LL cal()
    {
        int len=0;
        while(n)
        {
            digit[len++]=n%10;
            n/=10;
        }
        return DFS(len-1,0,1);
    }
    
    int main()
    {
        int i,j,T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%I64d",&n);
            memset(dp,-1,sizeof(dp));
            printf("%I64d
    ",cal());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    关于树及其各种操作
    正交矩阵与齐次矩阵
    矩阵的行列式与矩阵的逆
    线性变换
    矩阵
    向量的运算
    求两直线的交点
    微任务防抖
    二项分布
    二项式定理
  • 原文地址:https://www.cnblogs.com/zsboy/p/3329602.html
Copyright © 2011-2022 走看看