zoukankan      html  css  js  c++  java
  • 数位DP

      数位DP是用记忆化搜索做的。个人觉得比较难理解。很对函数中的参数比如前导零什么意思也没有说明,所以导致难以学习。

      记忆化搜索dfs(int len,int pre,int limit); 第二个参数是前导,主要是为了筛选。比如不要1到100000中不要连续数字62,此时你要要记录前导为6,然后你在当前dfs函数中变量时,判断i==2时,不符合要求。limit时一个上限制。

     看题目:hdu2089

    dp[10][2]存储是否是前缀有6的数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int dp[10][2],bit[10];
    
    int dfs(int len,bool if6,bool limit)
    {
        if(!len) return 1;
        if(!limit && dp[len][if6]!=-1) return dp[len][if6];
        int res=0,up = limit ? bit[len] : 9;
        for(int i=0;i<=up;++i)
        {
            if(i==4 || if6&&i==2) continue;
            res += dfs(len-1,i==6,limit&&i==up);
        }
        //不是limit表示里面有0-9的数字
        if(!limit) dp[len][if6] = res;
        return res;
    }
    int fun(int n)
    {
        int len = 0;
        while(n)
        {
            bit[++len] = n%10;
            n /= 10;
        }
        return dfs(len,false,true);
    }
    int main()
    {
        memset(dp,-1,sizeof(dp));
        int a,b;
        while(~scanf("%d%d",&a,&b),a&&b)
        {
            printf("%d
    ",fun(b)-fun(a-1));
        }
        return 0;
    }

     hdu3555

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    long long dp[20][2],bit[20];
    
    long long dfs(int len,bool if4,bool limit)
    {
        if(!len) return 1;
        if(!limit && dp[len][if4]!=-1) return dp[len][if4];
        long long res=0,up = limit ? bit[len] : 9;
        for(long long i=0;i<=up;++i)
        {
            if(if4 && i==9) continue;
            res += dfs(len-1,i==4,limit&&i==up);
        }
        if(!limit) dp[len][if4] = res;
        return res;
    }
    long long fun(long long n)
    {
        int len = 0;
        while(n)
        {
            bit[++len] = n%10;
            n /= 10;
        }
        return dfs(len,false,true);
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        memset(dp,-1,sizeof(dp));
        while(t--)
        {
            long long n;
            scanf("%lld",&n);
            printf("%lld
    ",n-(fun(n)-1));
        }
        return 0;
    }
    View Code

    hdu4722 简单题

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int bit[20];
    long long dp[20][10];
    
    long long dfs(int len,int pre,bool limit)
    {
        if(!len){if(pre==0) return 1;return 0;}
        if(!limit && dp[len][pre] != -1) return dp[len][pre];
        long long res = 0,up = limit ? bit[len] : 9;
        for(int i=0;i<=up;++i)
        {
            res += dfs(len-1,(pre+i)%10,limit && i==up);
        }
        if(!limit) dp[len][pre] = res;
        return res;
    }
    long long fun(long long n)
    {
        int len = 0;
        while(n)
        {
            bit[++len] = n%10;
            n /= 10;
        }
        return dfs(len,0,true);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        for(int t=0;t<T;++t)
        {
            memset(dp,-1,sizeof(dp));
            printf("Case #%d: ",t+1);
            long long a,b;
            scanf("%lld%lld",&a,&b);
            printf("%lld
    ",fun(b) - fun(a-1));
        }
        return 0;
    }
    View Code

    hdu3652 多维度数位DP

    hdu5435 亦或

    hdu4507 恨七不成妻

  • 相关阅读:
    HDOJ 1207 汉诺塔II
    [转]写代码的小女孩
    POJ Subway tree systems
    HDOJ 3555 Bomb (数位DP)
    POJ 1636 Prison rearrangement (DP)
    POJ 1015 Jury Compromise (DP)
    UVA 10003
    UVA 103 Stacking Boxes
    HDOJ 3530 Subsequence
    第三百六十二、三天 how can I 坚持
  • 原文地址:https://www.cnblogs.com/jlyg/p/7610449.html
Copyright © 2011-2022 走看看