【hdu-2089】不要62(数位DP入门)

题目链接:点击打开链接


【题意】

给定一段区间(0~1000000),求这段区间内不含62和4的个数


【个人感悟】
第一次做数位DP,查阅了好多资料,有用递推做的,也有用记忆化搜索做的,我主要针对记忆化搜索做谈谈我对数位dp的拙见。当然这道题是0~1000000,打表也是可以过的。

数位dp之所以不会超时,就在于他在数位搜索中添加了记忆化功能,即为mem数组,mem[i][j],i代表i位数,j代表上一位是否为6两种状态,当搜索过相同的mem[i][j]时,return 即可,但是有一个前提条件limit != 0,意思就是假如要搜索256以内的数,对于相同的56,百位为1和为2有不同的结果,因为百位为2有limit限制。这篇题解讲得很好


#include 
#include 
#include 
using namespace std;
int bit[8], mem[8][2];
//dfs返回结果,即一个len位的符合要求的数的个数
int dfs(int len, bool lim, bool preis_6)
{
    if(len == 0) return 1;//递归一定先考虑退出条件
    if(!lim && mem[len][preis_6] != -1) return mem[len][preis_6];
    int up = lim? bit[len] : 9;
    int ans = 0;
    for(int i = 0; i <= up; i++)
    {
        if(i == 4 || preis_6 && i == 2) continue;
        ans += dfs(len - 1, lim && i == up, i == 6);//直接把dfs看成返回的结果数
    }
    if(!lim) mem[len][preis_6] = ans;
    return ans;
}
int sol(int n)
{
    int len = 0;
    while(n)
    {
        bit[++len] = n % 10;
        n /= 10;
    }
    return dfs(len, 1, 0); 
}
int main()
{
    int n, m;
    while(scanf("%d%d", &m, &n),m+n)
    {
        memset(mem, -1, sizeof mem);
        printf("%d\n", sol(n) - sol(m-1));//因为搜索是包括的数本身的,所以要m-1
    }
    return 0;
}


你可能感兴趣的:(动态规划-DP)