各种DP分类

news/2025/1/17 8:30:51/文章来源:https://www.cnblogs.com/EmilyDavid/p/18676082

基本原理

三个条件:

  1. 最优子结构:能将大问题分解成小问题,并且大问题的最优解能通过小问题的最优解构成。
  2. 无后效性:已经求解的子问题,不会再受到后续决策的影响。
  3. 子问题重叠:可以用数组存下重叠的子问题来提升效率。

基本思路:

  • 将原问题分解成若干个阶段,找出每个阶段对应的子问题的特征(称为状态
  • 找每个状态可能的决策,即各状态之间的转移方式(称为状态转移方程
  • 找方程的边界,确定转移的顺序

(可以按顺序递推着写,不好确定顺序时也可以记忆化搜索

本质上可以对应到图上,状态为节点,决策为边,构成DAG,按拓扑序递推。

线性DP

LIS & LCS

LIS(Longest Increasing Subsequence 最长上升子序列)

计算序列\(A\)的LIS

Sol:

定义\(f_i\)表示考虑到前\(i\)个数,以第\(i\)个数结尾的LIS长度(状态)。

\(f_i=\max\limits_{j<i \land a_j<a_i} f_j+1\)(状态转移方程)

\(f_1=1\)(边界)

从前往后转移即可(顺序)。

最后\(ans=\max\limits_{i=1}^n f_i\)

\(O(n^2)\)

Another Sol:

上面的算法太慢了,考虑优化。

\(f_i\)表示所有长度为\(i\)的LIS最后一项的最小值,特别地,若长度为\(i\)的LIS不存在,则\(f_i=INF\)

下面证明:随着\(i\)增大,\(f_i\)单调递增。

运用反证法。假设存在\(x<i\),使得\(f_x>f_i\),那么在以\(f_i\)结尾的长度为\(i\)的LIS中可以分离出以\(f_i\)结尾的长度为\(x\)的LIS,这与\(f_x\)的最小性矛盾。所以命题得证。

现在来考虑以\(i\)结尾的LIS的长度\(dp_i\),由于我们要计算所有满足\(a_j<a_i\)\(j\)\(dp_j\)的最大值,不妨设最大的\(dp_j=x\)

由于\(a_i>a_j \land f_x \leq a_j\),故总有\(a_i>f_x\)

又由于\(f_i\)单调递增,因此我们要找到最大的\(x\)满足\(f_x<a_i\),考虑二分。

二分出\(x\)后,\(dp_i \gets x+1\)即可。还要更新\(f\),我们只需更新\(f_{dp_i}\),这是因为\(f_1,f_2 \dots f_{dp_i-1}\)都小于\(a_i\)\(f_{dp_i}\)是第一个大于等于\(a_i\)的。

\(O(n\log n)\)

其他类似问题,最长下降子序列,最长不升子序列,最长不降子序列,考虑的方式是类似的。所以记住LIS的推导即可。

LCS(Longest Common Subsequence 最长公共子序列)

求序列\(A\)和序列\(B\)的LCS

Sol:

定义\(f_{i,j}\)表示考虑序列\(A\)中的前\(i\)个以及序列\(B\)中的前\(j\)个时LCS的长度。

考虑转移:

\[f_{i,j}=\max(f_{i-1,j},f_{i,j-1},f_{i-1,j-1}+[a_i=b_j]) \]

前两项是继承,第三项是尝试拓展。

边界:\(f_{0,0}=0\)

从前往后转移即可。

\(O(n^2)\)

Another Sol:

上面的算法太慢了,考虑优化。

我们把序列\(A\)离散化成一个排列,序列\(B\)与之对应。

再将排列中的每个数对应到它的下标,则序列\(A\)变成一个从\(1\)\(n\)的序列,序列\(B\)与之对应。

此时LCS长度不变(这由映射关系是显然的),并且注意到LCS的长度等于序列\(B\)的LIS的长度。

于是转到对LIS的优化。

(注意序列\(B\)中的元素要都在序列\(A\)中出现过才能使用这种方法)

\(O(n\log n)\)

背包

01背包

\(n\)个物品,背包容量为\(m\),每个物品有体积\(v_i\)(有时也叫重量或者其他类似概念)和价值\(w_i\),每个物品只能取\(1\)次,求在物品总体积不超过背包容量的情况下能得到的最大价值。

Sol:

定义\(f_{i,j}\)表示考虑了前\(i\)个物品,背包容量为\(j\)时可以得到的最大价值。

\(f_{i,j}=\max(f_{i-1,j},f_{i-1,j-v_i}+w_i)\)

前一项是继承,后一项是尝试做选择第\(i\)个物品的决策。

\(f_{0,0}=0\)

从前往后转移即可。

\(O(nm)\)

代码实现可以压掉第一维,但注意转移顺序,要倒着转移(显然的,看转移方程)。

回退背包

自己起的名字。可能不叫这个。

01背包算好后其中的物品是无序的,可以随便钦定一个物品作为最后一个加入的,然后倒着跑背包撤销这个物品的影响。

注意这个东西只能在信息支持简单撤销时能用,比如加法改成减法,求\(\max\)之类的就不行了。

P4141 消失之物

完全背包

与01背包类似,但一个物品可以取无限次。

有两种解决方式:

The First Sol:

把每种物品拆成每\(2^k\)个一组(二进制分组),显然分的组是有限个,对这些组跑01背包。

The Second Sol:

同01背包定义\(f_{i,j}\)

\[f_{i,j}=\begin{cases} f_{i-1,j} & j<v_i\\ f_{i,j-v_i}+w_i & Otherwise. \end{cases} \]

注意到与01背包的区别只在于做决策时的下标。

第一维同样可以压掉,但是注意转移顺序,正着转移即可。

\(O(nm)\)

多重背包

与01背包类似,但第\(i\)个物品有\(s_i\)个。

Sol:

考虑二进制分组,每\(2^k\)个分一组,最后不足的单独分一组。

可以证明这样可以组合出每一种决策。

然后转化为01背包做。

\(O(nm\log s)\)

混合背包

01背包、完全背包、多重背包混在一起。

Sol:

分类讨论一下,把三种代码拼在一起。

或者都用二进制分组。

二维(多维)费用背包

在背包物品要消耗体积外还有其他费用(比如重量、时间等)。

Sol:

多开几维,同样可以把枚举第\(i\)个物品的第一维压掉。

分组背包

与01背包类似,但是每组内的物品只能选一个。

Sol:

每组之内做一次01背包。

具体而言,定义\(f_{i,j}\)表示考虑到第\(i\)组,背包容量为\(j\)时能获得的最大价值。

每一组内枚举其中的物品尝试转移。

更一般的线性DP

难点在于消除可能的后效性。

在线性DP中我们通过观察题目性质和优化状态设计来做到这一点。

有时会设计出形如\(f_{i,s}\)的状态表示考虑了前\(i\)个,最后一组的状态为\(s\)时的最优解,一般可以把\(s\)这一维优化掉。

区间DP

区间DP其实是特殊的线性DP,以区间长度为阶段。

基本思想是从小区间转移到大区间。

一般很板,就是从小到大枚举区间,然后枚举断点转移。

状态一般设为\(f_{l,r}\)表示\([l,r]\)这段区间的最优解。

有二维的形式,也类似,状态设为\(f_{x_1,y_1,x_2,y_2}\)表示左上角为\((x_1,y_1)\),右下角为\((x_2,y_2)\)的矩形的最优解,枚举断点改为枚举断开的行或列。

处理环

一般断环成链,将原数组复制一份接在后面即可。

转移涉及当前区间最值

可以看做是在笛卡尔树的结构上进行DP。

状压DP

本质是将一种状态压缩为一个数进行DP,除此之外与其他DP类似。

注意可以预处理出所有可行状态以提高运行效率。有时这样复杂度才正确

高级的状压:插头DP。

树形DP

一般的树形DP

只是将DP的操作放到树上,利用树很好的递归性质求解。

一般定义状态为\(f_{u,s}\)表示在\(u\)的子树内限制为\(s\)的最优解。

尝试从\(son/fa\)转移。

树上背包

就是把背包放到树上。

定义状态为\(f_{u,i,j}\)表示在\(u\)的子树内,考虑了前\(i\)个儿子,背包容量为\(j\)时能获得的最大价值。

转移:\(f_{u,i,j}=\max\limits_{v \in son_u,k \le j\land k\le siz_v} f_{u,i-1,j-k}+f_{v,siz_v,k}\)

注意边界,手推一下。

第二维可以压掉,但要倒序枚举\(j\)(显然的,看转移方程)。

树上换根

也叫二次扫描,通常要两次DFS。第一次进行一些预处理,第二次开始DP

转移时可以考虑从父亲转移到儿子(因为一般以\(1\)为根时的答案可以在第一次DFS后简单地算出来,然后向下转移)。

关注换根时答案的变化量。

数位DP

问题特征

  • 目的是统计满足某种限制的数的个数。

  • 限制是针对数位的。

  • 提供统计的区间或上界。

  • 上界很大,但只看数位个数可以接受。

基本原理

有一个通用答案数组,其中记录在计数过程中大量重复出现的过程的答案(如统计\(1000\)\(1999\)的答案和\(2000\)\(2999\)的答案,后三位都是\(000\)\(999\),可以单独记录下来)。

这个通用答案数组根据题目限制进行DP

区间的询问通常拆成两个区间相减。

统计答案部分可以记忆化搜索,也可以递推。从高到低枚举每一位,注意贴上限时的处理(如上限为\(12345\),现在填的前三位为\(123\))。

部分套路:

\(i\)位上能填的数与前面填的数相关。

定义状态为\(f_{i,s,op}\)表示当前考虑到第\(i\)位,前缀的状态为\(s\),第\(i\)位与前缀的关系为\(op\)

根据题意尝试转移。

还可以尝试继续压缩常数,参数里面能相互推的压在一起。

记忆化搜索

记搜大法吼!

记搜长得很板,方便拓展。

一般先将边界数字拆到数位上,然后从高位到低位填数。用个数组记忆化一下。

一般有以下形参:

  • \(pos\):当前枚举到的位置。

  • \(lim\):第\(pos\)位是否受限(前几位是否贴上界)。初始时可以理解为前面都贴了\(0\)的上界。

  • \(lead\):第\(pos\)位前面是否有前导零。前导零与答案有关时才记,零只有在不是前导零时才算贡献。

接着是根据题意得到的限制条件,记搜时要作为状态的一部分塞到形参里以及状态里。

考虑用于记忆化的数组\(f\)\(f_{i,op}\)表示当前\([len,pos+1]\)都填好了,且满足限制\(op\)\([1,pos]\)随便填(这就要求!lim&&!lead(没有限制)才能返回\(f\))的答案。

计数DP

特征:计算满足限制的方案总数。

注意计数时要求的不重不漏。有重复时考虑容斥减掉或者设计一种DP顺序使方案不重复。

一般是数学推式子再套上DP

概率期望DP

就是概率期望相关的数学推式子套上DP

一些套路:

对于概率DP,一般是正着DP,即定义状态\(f_i\)表示从初状态到状态\(i\)的概率。

对于期望DP,一般是倒着DP,即定义状态\(f_i\)表示从状态\(i\)到末状态的期望。(有些题目也可以正着DP,但是有些麻烦)

插头DP

连通性相关的状压DP。

适用于各种网格覆盖相关且允许状压的问题。

SOS DP

Sum Over Subset DP,子集和DP。是特殊情况的高维前缀和。

每一维只是\(0\)/\(1\)的情况比较常见,比如二进制数视作集合,然后求\(a_i\)中子集的和。

表述更为清晰一点的例子是,求\(a_{1\dots n}\)中有多少个\(i\)满足\(a_i \And k=k\)

复杂度与值域有关,设值域为\(V\),则复杂度为\(O(V\log V)\)

现在来讲做法,设\(f_{i,j}\)表示前\(i\)位与\(j\)可以不同,其他位必须相同的子集的和。

那么就有分讨了:

  1. \(j\)的第\(i\)位为\(0\),那么必须选\(0\)\(f_{i,j}\)加上\(f_{i-1,j}\)

  2. \(j\)的第\(i\)位为\(1\),则\(f_{i,j}\)加上\(f_{i-1,j}+f_{i-1,j\oplus 2^i}\)

这样就不重不漏地数完了。

超集和DP也是类似的,分讨一下就做完了。

和数位DP有一定相似性,但侧重点不同。数位DP擅长处理一段连续区间中的数数问题,而SOS DP擅长处理不那么连续,而是较为离散的点的数数问题,而且点的权值可以任意给,缺点是复杂度太高。

有后效性的DP的处理方法

一般是按某个值排序(如DP值,而且不是真的排序,只是规定了顺序)。

然后可以按照类似跑最短路的方式转移。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/870636.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Typora Markdown编辑器

Typora Markdown编辑器 Typora for Mac是一款功能丰富、界面简洁优雅的Markdown编辑器,它既简单易用,又具有丰富的功能。无论您是写作爱好者还是专业人士,Typora都能帮助您提高写作效率,制作出清晰、专业的文档。

在Mac上快速运行Windows软件,玩黑神话悟空、办公-CrossOver

CrossOver 在Mac上快速运行Windows软件-安装 CrossOver 可以在 Mac 上运行成千上万的 Windows 程序。从办公软件、实用工具、游戏到设计软件,只需在 Mac 的 dock 轻按一下便可运行。您可以 Windows 程序和 Mac 程序之间随意切换,而这一切无需重启、无需虚拟机,也无需购买 Wi…

MAC|win——NTFS和APFS文件系统

问题:2T的Windows机械硬盘+读写器+转接头,连接到Mac,能读取机械硬盘里的内容,但是,无法写入(新建目录、写入文件)。 答案: NTFS(New Technology File System)和APFS(Apple File System)分别是微软和苹果推出的文件系统,它们在设计理念、性能、兼容性和应用场景上各…

Synfig Studio 1.5 (Linux, macOS, Windows) - 开源 2D 动画软件

Synfig Studio 1.5 (Linux, macOS, Windows) - 开源 2D 动画软件Synfig Studio 1.5 (Linux, macOS, Windows) - 开源 2D 动画软件 Open-source 2D Animation Software 请访问原文链接:https://sysin.org/blog/synfig-studio/ 查看最新版。原创作品,转载请保留出处。 作者主页…

LibreOffice 24.8 (Linux, macOS, Windows) - 自由免费的全能办公套件

LibreOffice 24.8 (Linux, macOS, Windows) - 自由免费的全能办公套件LibreOffice 24.8 (Linux, macOS, Windows) - 自由免费的全能办公套件 professional FREE and open source painting program 请访问原文链接:https://sysin.org/blog/libreoffice/ 查看最新版。原创作品,…

UWP 部署失败 DEP0700 0x80073CF0 错误 0x800701C0 从位置 AppxManifest.xml 中打开文件失败

具体的错误内容如下 DEP0700: 应用程序注册失败。[0x80073CF0] 错误 0x800701C0: 从位置 AppxManifest.xml 中打开文件失败,错误为: 无法遍历该路径,因为它包含不受信任的装入点。 对应的英文版错误大概内容如下 DEP0700: Registration of the app failed. [0x80073CF0] erro…

【ChatGPT】Mr. Ranedeer 个性化学习定制

Mr. Ranedeer 是ChatGPT 的一个插件,它可以用来定制任何学习路线,并且在你学习的过程中,对你不了解或者有错误i的地方进行改正并加以练习。 你的学习风格、沟通方式、沟通类型、语气和推理框架,Mr. Ranedeer 都能为你做到全方面私人定制。使用的过程中,非氪金玩家尽量使用…

似乎没有提供具体文章内容或者特定样式段落数量的要求以下是一个基本示例这里创造一个简单的标题来的文章使…………似乎没有提供具体文章内容或者特定样式、段落数量的要求,以下是一个基本示例。这里创造一个简单的标题《来》的文章,使用 ` ` 标记创建标题,然后在不同 `p` …

举例说明HTML5的Canvas元素有什么用途?

HTML5 的 <canvas> 元素是一个非常强大的工具,它提供了一个画布,允许开发者使用 JavaScript 来绘制图形、动画,甚至创建复杂的游戏。以下是一些 <canvas> 元素的主要用途:图形绘制:使用 <canvas>,你可以绘制各种基本图形,如线条、矩形、圆形、多边形等…

[2025.1.17 JavaSE学习]文件基础知识

文件 什么是文件文件,即保存数据的地方,具有各种形式文件流 文件在程序中是以流的形式来操作的

人机交互笔记

什么是人机交互 人机交互(HCI)是一门多学科研究领域,侧重于计算机技术的设计,特别是人(用户)与计算机之间的交互。Nielsons heurisitcs 1. Visibility of system status - how well the state of a system is conveyed to its user - 用户能够收到信息反馈,知道系统当前…

【Spring Security】初识 Spring Security

# Spring Security Spring Security 是 Spring 家族中历史比较悠久的框架,具备完整而强大的功能体系。本专栏内,我们将正式体系化了解 Spring Security,并围绕它的功能体系展开讨论。 一、初识 Spring Security 其实在 Spring Boot 出现之前,Spring Security 就已经诞生…