浅谈数位dp

Posted tombraider-shadow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈数位dp相关的知识,希望对你有一定的参考价值。

此博客收集了其他队员中写的比较完整的一篇博客,对于其中的东西解释已经很完善

不再做过的阐述,链接在此     ——————

(链接的博主渴望大家的赞)

我只对上述博客的最后一个AC代码做出解释形阐述

只是我的个人理解,对一些难理解的地方做出注释以及个人的微不足道的理解

此代码的dp储存的是第i为上是六(dp[i][1])和不是6(dp[i][0])的情况

#include<stdio.h>
#include<string.h>
 
int n, m;
int dp[20][10], digit[8];
 
int dfs(int pos, int pre, int limit)
{
    if(pos == 0)// 递归边界,已经枚举结束,则1个数满足条件
        return 1;
    if(!limit && dp[pos][pre] != -1) // 已经搜索过的不再搜索,直接使用之前的计算结果
        return dp[pos][pre];
    int ans = 0;
    int maxd = limit ? digit[pos] : 9;
    for(int i = 0; i <= maxd; i ++)
    {
        if(i == 4 || (i == 2 && pre == 6)) // 枚举数字,如果数字不同则枚举0-9
            continue;
        ans += dfs(pos - 1, i, limit && i == digit[pos]);
    }
    if(!limit)            //当没有上限的时候才需要保存此值
        dp[pos][pre] = ans;
    return ans;
}
 
int count(int n)
{
    int len = 0;
    while(n)
    {
        digit[++ len] = n % 10;
        n /= 10;
    }
    return dfs(len, 0, 1);//刚开始递归的时是从最高为开始递归的,所以上限为true,而由于最高为是从0开始dfs的,所以if6为false
}
 
int main()
{
    memset(dp, -1, sizeof(dp));
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        if(n == 0 && m == 0)
            break;
        printf("%d\\n", count(m) - count(n - 1));
    }
    return 0;
}

 

以上是关于浅谈数位dp的主要内容,如果未能解决你的问题,请参考以下文章

浅谈数位dp——hdu 不要62

专题数位DP

一天一DP计划数位dp

数位dp

P4127 [AHOI2009]同类分布

kotlin-从一个片段更改多个片段的小数位