news 2026/6/15 17:41:10

数位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/6/15 12:48:53

<Linux基础11集>电流+二极管+晶体管+存储器

零 感觉上一集写的不太好,不清晰,没有用自己的话描述 再来一遍 物质的组成 原子(不带电)包括 原子核 和 核外电子(带负电) 原子核包括 质子(带正电) 和 中子 (质子所带的正电量核外电子所带的负电量) 电流的形成 自由电子定向移动形成电流 导体导电的原因 部分电子可以…

作者头像 李华
网站建设 2026/6/15 12:56:20

前后端分离失物招领平台系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程

摘要 随着城市化进程的加快和人口流动性的增强&#xff0c;日常生活中物品遗失的现象日益频繁&#xff0c;传统的失物招领方式效率低下且信息传播范围有限。为解决这一问题&#xff0c;基于前后端分离架构的失物招领平台系统应运而生。该系统通过互联网技术整合失物信息&#…

作者头像 李华
网站建设 2026/5/11 3:41:27

基于Android手机平台的求职招聘 开题报告

目录 研究背景与意义国内外研究现状研究内容技术路线创新点预期成果进度安排 项目技术支持可定制开发之功能亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作 研究背景与意义 随着移动互联网普及&#xff0c;求职招聘逐渐从PC端转向移动…

作者头像 李华
网站建设 2026/6/15 15:35:36

基于Android校园新闻APP开发的设计 开题报告

目录 研究背景与意义目标与功能设计技术选型创新点预期成果进度计划 项目技术支持可定制开发之功能亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作 研究背景与意义 随着移动互联网的普及&#xff0c;校园信息传递效率成为师生关注的焦…

作者头像 李华
网站建设 2026/6/15 12:51:22

企业级毕业设计成绩管理系统管理系统源码|SpringBoot+Vue+MyBatis架构+MySQL数据库【完整版】

摘要 随着高等教育信息化的快速发展&#xff0c;毕业设计成绩管理作为高校教学管理的重要环节&#xff0c;亟需通过数字化手段提升效率与准确性。传统的人工管理方式存在数据易丢失、统计效率低、信息共享困难等问题&#xff0c;难以满足现代高校对教学管理的精细化需求。基于…

作者头像 李华
网站建设 2026/6/15 12:54:47

【2025最新】基于SpringBoot+Vue的+电商应用系统管理系统源码+MyBatis+MySQL

摘要 随着互联网技术的快速发展和电子商务的普及&#xff0c;电商应用系统在商业活动中扮演着越来越重要的角色。传统的线下商业模式逐渐向线上转移&#xff0c;企业对高效、安全、可扩展的电商管理系统的需求日益增长。电商系统不仅需要支持商品展示、订单管理、支付结算等核…

作者头像 李华