1. 引言过河卒是 NOIP 2002 普及组的一道经典题目也是很多初学者接触动态规划与记忆化递归的第一道题。题目本身并不复杂但其中蕴含的「重复子问题」思想却是理解递归优化、动态规划乃至更高级算法的基础。本文不打算只给出一个能 AC 的代码而是想借这道题认真聊一聊记忆化递归Memoization背后的思考方式为什么朴素递归会超时记忆化到底「记」了什么它和递推动态规划又是什么关系2. 题目回顾2.1 题目描述棋盘上 A 点有一个过河卒需要走到目标 B 点。卒行走的规则可以向下、或者向右。同时在棋盘上的任一点有一个对方的马如下图该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此这匹马的控制点卒不能通过。棋盘用坐标表示A 点(0, 0)、B 点(n, m)n、m 为不超过 20 的整数同样马的位置坐标是需要给出的。现在要求你计算出卒从 A 点能够到达 B 点的路径条数。2.2 输入输出格式输入一行四个正整数分别表示 B 点坐标(n, m)和马的坐标(x, y)。输出一个整数表示从 A 到 B 的路径条数。2.3 样例输入6 6 3 3输出63. 朴素递归直观但低效3.1 递归的直觉卒只能向下或向右走那么从(i, j)到(n, m)的路径数自然可以拆成「从(i1, j)出发的路径数」加上「从(i, j1)出发的路径数」。写成递归就是intdfs(inti,intj){if(in||jm)return0;// 越界if(injm)return1;// 到达终点if(isControl(i,j))return0;// 马的控制点returndfs(i1,j)dfs(i,j1);// 向下 向右}这个写法非常符合直觉代码也极短。但它的时间复杂度是指数级的因为同一个状态(i, j)会被反复计算很多次。3.2 为什么慢重复子问题以(0, 0)出发为例dfs(1, 1)既会被dfs(0, 1)调用又会被dfs(1, 0)调用。随着棋盘变大这种重复会呈爆炸式增长。我们可以画一棵递归树来观察每个节点向下分裂出两个子节点树的高度约为n m因此节点总数约为2^(nm)。当n m 20时这个量级是天文数字必然超时。4. 记忆化递归把算过的结果存下来4.1 核心思想既然同一个状态会被重复计算那不如「算一次存起来下次直接用」。这就是记忆化递归——用空间换时间。具体做法开一个二维数组memo初始化为-1表示「还没算过」。每次进入dfs(i, j)时先查表如果已经算过直接返回缓存值否则计算并写入缓存。#includebits/stdc.husingnamespacestd;intn,m,x,y;longlongmemo[25][25];boolcontrol[25][25];boolisControl(inti,intj){returncontrol[i][j];}longlongdfs(inti,intj){if(in||jm)return0;if(injm)return1;if(isControl(i,j))return0;if(memo[i][j]!-1)returnmemo[i][j];// 命中缓存returnmemo[i][j]dfs(i1,j)dfs(i,j1);// 计算并缓存}intmain(){cinnmxy;memset(memo,-1,sizeof(memo));// 标记马的控制点intdx[]{1,1,-1,-1,2,2,-2,-2};intdy[]{2,-2,2,-2,1,-1,1,-1};control[x][y]true;for(intk0;k8;k){intnxxdx[k],nyydy[k];if(nx0nxnny0nym){control[nx][ny]true;}}coutdfs(0,0)endl;return0;}4.2 复杂度分析经过记忆化后每个状态(i, j)最多只计算一次状态总数约为(n1) × (m1)因此时间复杂度降为O(n × m)空间复杂度同样为O(n × m)。相比指数级的朴素递归这是质的飞跃。5. 记忆化递归 vs 递推动态规划5.1 两者的关系记忆化递归和递推自底向上的动态规划本质上是同一件事的两种写法记忆化递归自顶向下从大问题出发递归拆解到小问题用缓存避免重复。递推自底向上先算小问题再逐步组合成大问题。两者都依赖「最优子结构」和「重叠子问题」这两个性质区别只是计算顺序。5.2 各自的优缺点维度记忆化递归递推思考方式贴近自然递归容易写需要先想清楚状态转移顺序代码量通常更短有时更繁琐只算需要的状态是按需计算否可能算多余状态递归栈风险有深度大时可能爆栈无常数开销略大函数调用 查表更小对于过河卒这种状态转移方向非常明确的题目递推往往更简洁但对于状态转移关系复杂、难以确定计算顺序的题目记忆化递归往往更省心。5.3 递推写法参考#includebits/stdc.husingnamespacestd;intn,m,x,y;longlongdp[25][25];boolcontrol[25][25];intmain(){cinnmxy;intdx[]{1,1,-1,-1,2,2,-2,-2};intdy[]{2,-2,2,-2,1,-1,1,-1};control[x][y]true;for(intk0;k8;k){intnxxdx[k],nyydy[k];if(nx0nxnny0nym){control[nx][ny]true;}}dp[0][0]1;for(inti0;in;i){for(intj0;jm;j){if(control[i][j]){dp[i][j]0;continue;}if(i0)dp[i][j]dp[i-1][j];if(j0)dp[i][j]dp[i][j-1];}}coutdp[n][m]endl;return0;}6. 记忆化递归的通用套路从过河卒这道题我们可以提炼出记忆化递归的通用三步法定义状态明确dfs(i, j)表示什么参数要能唯一确定一个子问题。写出转移用自然递归的方式写出状态之间的关系。加缓存在递归入口先查缓存计算后写入缓存。这个套路几乎适用于所有「递归会重复计算」的问题比如斐波那契数列、爬楼梯、数字三角形、背包问题等。掌握了它你就掌握了一把处理重叠子问题的通用钥匙。7. 总结过河卒虽然是一道入门题但它完美地展示了记忆化递归的核心价值识别重复子问题并用缓存消除重复计算。朴素递归直观但指数级超时记忆化递归用空间换时间把复杂度降到多项式级记忆化递归与递推是同一思想的正反两面各有适用场景。希望这篇文章能帮你真正理解记忆化递归的「为什么」和「怎么做」。下次再遇到递归超时不妨先想一想是不是有重复子问题能不能用一张表把它记下来
企业数字化 ERP 产品动态
相关推荐
电子学会Python一级备考全攻略:从零基础到高分通过 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 6:22:40
卫星通信链路计算教案:核心公式、手算路径与避坑指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 6:22:34
荣耀出征原始点卡服正版官方客户端下载指引,忆往游戏正规安全渠道指南 《荣耀出征原始点卡服》由安徽游昕网络科技有限公司联合忆往游戏平台负责运营,是经过正版授权打造的奇迹 MU 怀旧手游。现阶段游戏依托专属官方主站面向全网正式开放,高度复刻奇迹 MU 端游原版内容,坚持点卡公平长久的运营模式,还… · 2026/9/27 6:22:34
一条 make 唤醒旧 iPhone:palera1n 越狱实操指南 一条 make 唤醒旧 iPhone:palera1n 越狱实操指南 【免费下载链接】palera1n Jailbreak for A8 through A11, T2 devices, on iOS/iPadOS/tvOS 15.0, bridgeOS 5.0 and higher. 项目地址: https://gitcode.com/GitHub_Trending/pa/palera1n
打开小程序弹出「需… · 2026/9/27 7:03:08
齐诺网站建设被黑挂马3步救急对比评测实操 齐诺网站建设被黑挂马3步救急对比评测实操 昨晚三点,后台突然弹出一条红色警报,提示网站存在高危恶意代码注入。那一刻心跳加速,脑子里全是“完蛋了”。你肯定也遇到过这种糟心事:明明每天盯着服务器日志,怎么还是防不住黑客的暗箭?… · 2026/9/27 7:02:49
acme-companion 基础使用指南:为 nginx-proxy 自动化签发与管理 ACME SSL 证书 云原生运维 【免费下载链接】acme-companion Automated ACME SSL certificate generation for nginx-proxy 项目地址: https://gitcode.com/gh_mirrors/ac/acme-companion 点击查看 免费下载 本指南讲解 acme-companion 与 nginx-proxy 协同部署的最基础、最常用方… · 2026/9/27 7:02:31
不会代码也能做?自助外贸网站建设新手入门避坑指南 不会代码也能做?自助外贸网站建设新手入门避坑指南 手里有产品,想开个独立站卖货给老外,但一听到“建站”俩字就头大?代码一行看不懂,找外包报价又动辄上万,还怕被坑。这种“自己不会代码想做网站”的焦虑,我见过太多创业团队负责人。别慌,今天咱们不… · 2026/9/27 7:02:31
上海企业都用什么网站从零搭建3档报价单 上海企业都用什么网站从零搭建3档报价单 上周刚帮一家浦东的制造业客户把新站上线,对方老板在群里发了句大实话:“以前那家建站公司,改个按钮位置拖了一周,气得我直接找你们重做。”这太真实了。在上海做企业官网,最怕的不是没效果,而是沟通成本高、响… · 2026/9/27 7:02:07
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01