news 2026/8/9 19:43:28

数位dp模版

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数位dp模版

直接放一篇比较有代表性的数位dp学习的题目链接和标准的题解代码,由于题解代码较少就懒得解释更多了,关键就是从高位到低位的状态dfs➕记忆化➕对区间答案拆解为前缀差

https://www.luogu.com.cn/problem/P13085

#include <iostream> #include <vector> #include <cmath> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; // dp[pos][pre] // pos: 当前处理到的位数 // pre: 上一位填写的数字 (0-9) // 因为 pre 有可能是前导零状态或者初始状态,我们在记忆化时通常只记录 lead=false 的情况 ll dp[20][15]; int a[20]; // 存储把数字拆解后的每一位 // dfs 函数 // pos: 当前位数 // pre: 上一位数字 // lead: 是否处于前导零状态 (true 表示前面全是 0) // limit: 最高位限制 (true 表示当前位受原数限制) ll dfs(int pos, int pre, bool lead, bool limit) { // 递归边界:填完了所有位,说明找到了一种合法方案,返回 1 if (pos == 0) return 1; // 记忆化搜索: // 如果没有最高位限制,且不是前导零状态,且该状态已经计算过,直接返回 if (!limit && !lead && dp[pos][pre] != -1) return dp[pos][pre]; // 当前这一位能填的最大数字 // 如果受 limit 限制,只能填到 a[pos];否则能填到 9 int up = limit ? a[pos] : 9; ll ans = 0; // 枚举当前位可能填的所有数字 i for (int i = 0; i <= up; i++) { // 判断当前填的 i 是否合法 // 情况 1: 之前全是前导零 if (lead) { if (i == 0) { // 如果当前继续填 0,则继续保持前导零状态,pre 不更新(或者传个特殊值,这里习惯用-2代表无前驱) // limit 更新:如果本来受限且当前填了上限(0==up),则继续受限 ans += dfs(pos - 1, -2, true, limit && (i == up)); } else { // 如果当前填了非 0,前导零状态结束。 // 因为是第一位有效数字,不需要和上一位比较差值,直接合法 ans += dfs(pos - 1, i, false, limit && (i == up)); } } // 情况 2: 之前已经有有效数字了 else { // 必须满足题目条件:相邻数字之差 >= 2 if (abs(i - pre) >= 2) { ans += dfs(pos - 1, i, false, limit && (i == up)); } } } // 记录状态(仅在无限制且非前导零时记录,因为 limit 和 lead 特殊情况复用率低) if (!limit && !lead) dp[pos][pre] = ans; return ans; } // 计算 [1, x] 之间的 Windy 数 ll solve(ll x) { int len = 0; // 把数字 x 拆解存入数组,比如 123 -> a[3]=1, a[2]=2, a[1]=3 while (x) { a[++len] = x % 10; x /= 10; } // 记忆化数组初始化为 -1 // 注意:如果是多次询问,且 dp 状态与 limit/lead 无关,其实 dp 数组只需要 memset 一次。 // 但为了保险和逻辑简单,这里每次 solve 都清空(实际上这题 dp 数组可以复用,放在全局只初始化一次更优) // 本题数据量较小,每次初始化也没问题,若 TLE 可移到 main 函数外 memset(dp, -1, sizeof(dp)); // 从最高位 len 开始搜,pre 初始设为 -2(一个不可能干扰 0-9 判断的数) return dfs(len, -2, true, true); } int main() { ll a, b; cin >> a >> b; // 答案是 [1, b] 的数量 减去 [1, a-1] 的数量 cout << solve(b) - solve(a - 1) << endl; return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/8 11:58:37

失物招领平台信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

摘要 随着城市化进程的加快和人口流动性的增强&#xff0c;物品遗失现象日益频繁&#xff0c;传统失物招领方式效率低下且信息传播范围有限。为解决这一问题&#xff0c;开发一套高效、便捷的失物招领平台信息管理系统具有重要意义。该系统通过整合线上线下资源&#xff0c;为…

作者头像 李华
网站建设 2026/8/8 11:58:55

前后端分离华府便利店信息管理系统系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程

摘要 随着信息技术的快速发展&#xff0c;传统便利店管理模式逐渐暴露出效率低下、数据冗余等问题。华府便利店作为一家中小型连锁企业&#xff0c;亟需一套高效、便捷的信息管理系统来优化商品管理、库存监控和销售分析等业务流程。信息化管理不仅能提升运营效率&#xff0c;…

作者头像 李华
网站建设 2026/8/8 0:55:12

如何选择西安优质小程序开发服务与本凡码农合作?

在选择西安优质小程序开发服务时&#xff0c;首先要清晰了解自己的需求。这个过程包括明确小程序的功能、设计风格及目标受众。其次&#xff0c;调查潜在开发公司的背景和案例&#xff0c;将其与市场中其他公司进行比较&#xff0c;确保其具备良好的口碑和丰富的项目经验。此外…

作者头像 李华
网站建设 2026/8/8 0:57:37

manictime pro 特别版安装教程下载

1. 安装 ManicTime 2025.3.8.0 2. 机活试用期&#xff0c;就是30天的那个 3. 关闭 ManicTime 进程 4. 将ManicTime.Client.dll文件复制到你安装的目录&#xff0c;注意不会覆盖文件 5. 运行 ManicTime 6.打开关于&#xff0c;显示以下就是成功了 导入旧个人数据库&#xff0c;…

作者头像 李华
网站建设 2026/7/31 7:02:53

Vibe Coding 与智能体:软件团队的新工作范式,以及我们该如何适应

近一年&#xff0c;软件研发正在出现一个非常明确的分水岭&#xff1a;一类团队开始用自然语言驱动开发&#xff0c;快速产出可运行的代码&#xff1b;另一类团队则把大模型变成“能干活的系统”&#xff0c;让它调用工具、执行流程、闭环交付。这两个关键词分别是 vibe coding…

作者头像 李华