数位dp



数位dp大致有两种写法,第一种是通过递推关系,推出不同状态之间的数学关系,预处理出dp数组内的数据。但这对数学的要求很高,一般人很难驾驭。

第二种是通过记忆化搜索,程序直白易理解,适合大多数情况下使用。


数位dp也是有模板的,因为核心思想都是差不多的。



#include <cstdio>
#include <cstring>

int dp[8][2];                                                     //dp数组存储什么信息视题目具体要求而定

int dfs (int * num, int pos, int status, bool limit) {            //status的含义也是需要取决于题意
    if (pos == 0) {
        return 1;
    }
    if (!limit && dp[pos][status] != -1) {
        return dp[pos][status];
    }
    int END = limit ? num[pos] : 9;
    int ans = 0;
    for (int i = 0; i <= END; i++) {
//        if (i == 4 || (status == 1 && i == 2)) {                 这一块是解决题目的核心代码
//            continue;
//        }
//        int tmp = status;
//        if (i == 6) {
//            tmp = 1;
//        }
//        else {
//            tmp = 0;
//        }
//        ans += dfs (num, pos - 1, tmp, limit && i == END);
    }
    if (!limit) {
        dp[pos][status] = ans;
    }
    return ans;
}

int solve (int x) {
    int num[8];
    int cnt = 0;
    while (x) {
        num[++cnt] = x % 10;
        x /= 10;
    }
    return dfs (num, cnt, 0, 1);
}

int main () {
    int n, m;
    memset (dp, -1, sizeof (dp));
    while (~scanf ("%d%d", &n, &m) && m) {
        printf ("%d\n", solve (m) - solve (n - 1));
    }
    return 0;
}


http://blog.csdn.net/wust_zzwh/article/details/52100392

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值