浅谈数位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的主要内容,如果未能解决你的问题,请参考以下文章