hdu 2089 不要62(数位dp入门)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089

一道数位dp的入门题,数据超级小完全可以用暴力过,当然用记忆化搜索写更好,能练练数位dp

的记忆化搜索的写法。

开始要找dp的设法,首先必要的一维是长度,然后第二维可以存前一个数也可以表示状态,这里

要选择表示状态。如果选择存前一个数这样不好,因为返回的dp要要求不含有不吉利的数字,所

以这里优先考虑dp[len]这些数是否要满足要求,所以第二维要设state表示状态,只返回状态满

足要求的dp值。

#include <iostream>
#include <cstring>
using namespace std;
int n , m , dp[12][3] , dig[12];
int dfs(int len , int state , int flag) {
    if(len == 0) {
        return state < 2;
    }
    if(!flag && state < 2 && dp[len][state] != -1) {
        return dp[len][state];
    }
    int t = flag ? dig[len] : 9;
    int sum = 0;
    for(int i = 0 ; i <= t ; i++) {
        if(state == 0) {
            if(i == 4) {
                continue;
            }
            else {
                if(i == 6) {
                    sum += dfs(len - 1 , 1 , flag && i == t);
                }
                else {
                    sum += dfs(len - 1 , 0 , flag && i == t);
                }
            }
        }
        if(state == 1) {
            if(i == 2 || i == 4)
                continue;
            else {
                if(i == 6) {
                    sum += dfs(len - 1 , 1 , flag && i == t);
                }
                else {
                    sum += dfs(len - 1 , 0 , flag && i == t);
                }
            }
        }
    }
    if(!flag && state < 2) {
        dp[len][state] = sum;
    }
    return sum;
}
int Gets(int x) {
    memset(dp , -1 , sizeof(dp));
    memset(dig , 0 , sizeof(dig));
    int len = 0;
    if(x == 0) {
        dig[++len] = 0;
    }
    while(x) {
        dig[++len] = x % 10;
        x /= 10;
    }
    return dfs(len , 0 , 1);
}
int main() {
    while(scanf("%d%d" , &n , &m) != EOF) {
        if(n == 0 && m == 0) {
            return 0;
        }
        printf("%d
" , Gets(m) - Gets(n - 1));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/TnT2333333/p/6152813.html