DP分析黑科技——闫氏DP分析法

(前置:没有在百度百科上找到,查了一下这种方法是由英国经济学家埃拉闫提出的(真·DP起源于经济学))

核心思想:从集合角度分析DP问题

在我们遇到的DP问题中,一般都是求在一个有限集内的最值,但是这些方案数量一般都是指数级别的,想要一个一个查找出来不太可能。所以DP方法是用来优化这种寻找最优方案的过程的。一般的DP分析方法是通过状态,阶段,子问题三个方面来推的,在学习过闫氏分析法之前我一直都是通过先写一遍暴搜再通过转移阶段来推状态转移方程,这种方法很慢,并且有一定理解差异,但是闫氏DP分析法可以从题目本身出发,通过划分集合的方式来代替推方程,使解题过程更加清晰明了。

我们在使用闫氏DP分析法解决DP问题时一般都要经历两个阶段

  1. 状态表示(化零为整,寻找共性):一般指把一些具有相似点的方案用一个状态来表示,简单点就是指把问题的答案存在一个状态中来求解。状态表示一般要从两个角度来分析
  • [1]集合:确定该状态表示的集合,比如0/1背包问题中,我们把 \(f[i][j]\) (未优化)表示为所有考虑前 \(i\) 个物品且总体积不超过 \(j\) 的最大价值方案的集合。我们通过用 \(f[i][j]\) 来表示一类问题而不是一个东西,这就是DP实现优化的本质
  • [2]属性:就是我们状态要存的这个值是这个集合的什么东西,也就是题目要求的最大值/最小值/数量等等
  1. 状态计算(化整为零,寻找不同):这里就是闫氏DP分析法与替他分析法最大的不同,具体的,我们要把它们划分成若干个不同的子集来求,每一个子集分别去求,比如说0/1背包问题我们将 \(f[i][j]\) 划分成可以发现我们将我们找到的状态划分为一个个子集,划分的依据为寻找最后一个不同点。这里还有两个要点:第一就是不要漏情况,这会导致你的状态转移方程错误从而寄掉;第二如果是在求值或是求数量的时候,要保证没有重复,否则就会导致结果出错。通过以上过程,我们实际上是把一个大的问题直接分为了几个小问题解决,这就是所说的化整为零。

例题:

一、背包DP

1. 0/1背包问题

题目链接

按照我们上面的闫氏DP分析法,我们得到以下过程这样,我们可以轻松得到未优化过的状态转移方程,代码如下

#include<bits/stdc++.h>
using namespace std;
const int N=1018;
int n,m,w[N],v[N],f[N][N];
int main(){scanf("%d%d",&m,&n);for(int i=1;i<=n;i++)scanf("%d%d",&v[i],&w[i]);for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){f[i][j]=f[i-1][j];if(j>=v[i])f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);}}printf("%d",f[n][m]);return 0;
}

注意到空间复杂度 \(O(NM)\) 会被黑心出题人给卡 \(MLE\) ,我们就不能用两维数组来解决这个问题,我们可以使用滚动数组解决,这里不过多讲解,有兴趣可以看看代码,这里我们在上面程序的基础上进行缩维优化。容易发现,在每个阶段转移时,我们实际上只是进行了一次从 \(f[i][]\)\(f[i-1][]\) 的拷贝操作,即我们可以将 \(f[i][j]\) 的第一维省略掉,即现在的状态表示为 \(f[j]\) 表示所有考虑到前 \(i\) 个物品,且背包内总体积不超过 \(j\) 的最大价值,同时我们省去上面程序中 \(if(j>=v[i])\) 的特判,将 \(j\)\(m\) 一直枚举到 \(v[i]\) ,这样就可以避免了当前总体积加上 \(v[i]\) 超过 \(j\) 的情况,于是我们就得到了新的状态转移方程: \(f[j]=max(f[j],f[j-v[i]]+w[i])\) 。优化代码如下

#include<bits/stdc++.h>
using namespace std;
const int N=1018;
int n,m,w[N],v[N],f[N],ans=-1;
int main(){scanf("%d%d",&m,&n);for(int i=1;i<=n;i++)scanf("%d%d",&v[i],&w[i]);for(int i=1;i<=n;i++)for(int j=m;j>=v[i];j--)f[j]=max(f[j],f[j-v[i]]+w[i]);for(int i=0;i<=m;i++)ans=max(ans,f[i]);printf("%d",ans);return 0;
}

2.完全背包

题目链接

这道题虽然只是上面那个题多加了一个可以取多次的条件,即状态表示过程于0/1背包相同,但用闫氏DP分析法可以发现状态计算过程与上面那个题完全不一样,0/1背包问题划分的依据是选或不选\(i\) 个物品,而完全背包问题划分的依据是选择几个\(i\) 个物品,分析过程为:我们发现这么推出来的状态转移方程需要三重循环,在 \(n=10^3\) 的级别下会 \(TLE\) ,我们要对其进行优化。

注意到:
\(f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i],f[i-1][j-2*v[i]]+2*w[i],······,f[i-1][j-k*v[i]]+k*w[i],······)\)

对于
\(f[i][j-v[i]]=max(f[i-1][j-v[i]],f[i-1][j-2*v[i]]+w[i],f[i-1][j-3*v[i]]+2*w[i],······,f[i-1][j-(k+1)*v[i]]+k*w[i],······)\)

可以发现第一个式子中 \(max(f[i-1][j-v[i]]+w[i],f[i-1][j-2*v[i]]+2*w[i],······,f[i-1][j-k*v[i]]+k*w[i],······)\) 就是第二个式子加上 \(w[i]\) 即第一个式子可以优化为:

\(f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i])\)

这样我们就得到了优化过后的状态转移方程,进而得到代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1018;
int f[N][N],n,m,w[N],c[N];
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d%d",&w[i],&c[i]);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){f[i][j]=f[i-1][j];if(j>=w[i])f[i][j]=max(f[i][j],f[i][j-w[i]]+c[i]); }printf("%d",f[n][m]);return 0;
}

但是这个题目有点阴间,直接把上面代码交上去会 \(RE\)\(50\) 分,因为这个题的 \(m\) 的范围开到了 \(10^5\) 级别,导致数组会爆炸(其实有点手法也能过),我们可以用滚动数组来做,也可以像0/1背包问题一样进行缩维,具体过程与0/1背包类似,在这不过多说明(),代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int m,n,w[N],v[N],f[N];
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d%d",&w[i],&v[i]);for(int i=1;i<=n;i++)for(int j=w[i];j<=m;j++)f[j]=max(f[j],f[j-w[i]]+v[i]);printf("%d",f[m]);return 0;
}

3.分组背包问题

题目链接

二、区间DP

1.石子合并

题目链接

这道题目大家也许并不陌生,通过题目描述我们发现石子最终会被合并成一堆,即该题为一个有限集,而且可以注意到一共有 \((n-1)!\) 种情况,而 \(n\) 的范围又是 \(n<=300\) ,所以直接枚举每种情况是不现实的,我们通过闫氏DP分析法来考虑DP做法:我们知道最后的答案一定是由两堆石子合并起来的,这就是这道题最后一个不同点,通过这个可以划分为不同子集,即最后两堆石子是从哪里开始分开的,对于每个 \(f[i][j]\) 可以从 \(i\) 一枚举到 \(j-1\) (因为要保证两段都有石子)为最后两堆石子的分界线,上图中是以 \(k (i<=k<=j-1)\) 为分界线做的例子,可以得到状态转移方程:

\(f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1])\)

\(s[]\) 数组可以通过前缀和来解决,代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1018;
int n,s[N],f[N][N];
int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&s[i]);s[i]+=s[i-1];//处理前缀和}for(int len=2;len<=n;len++){//枚举区间长度 for(int i=1;i+len-1<=n;i++){//枚举区间右端点 int j=i+len-1;//得到区间左端点 f[i][j]=1<<30;for(int k=i;k<j;k++)//枚举最后两堆得分界线 f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);}}printf("%d",f[1][n]);return 0;
}

2.回文字串

题目链接

三、线性DP

1.最长公共子序列问题(LCS)

题目链接

这道题相信大家已经很熟悉了吧,我们可以发现最坏情况下一一枚举是 \(2^n\) 的级别,是不现实的,我们还是用闫氏DP分析法来做DP做法,过程如下:累了,也许烂尾了吧,以后在写

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

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

相关文章

MUGEN游戏引擎等一系列相关杂谈

MUGEN游戏引擎等一系列相关杂谈也许是个相当没有质量的文章,或者说时定位错了 后面看情况出个整合包之类的吧...... 因此久违的想玩玩格斗游戏了,最好是那种全明星阵容打乱斗的 网上找了找,除了幻想印章,以外还有几…

龙岗网站建设公司河南头条最新消息 新闻

STM32 Proteus仿真LCD12864俄罗斯方块-FZ0063 Proteus仿真小实验&#xff1a; STM32 Proteus仿真LCD12864俄罗斯方块-FZ0063 功能&#xff1a; 硬件组成&#xff1a;STM32F103R6单片机 LCD12864显示器多个按键 1.标准俄罗斯方块经典游戏玩法&#xff0c;带计时&#xff0c…

门户网站的含义做淘宝详情页好的网站

.NET 8 是微软于2021年8月24日宣布的下一代编程语言和框架&#xff0c;它是 .NET 宇宙的一部分&#xff0c;与 C# (Common Language Infrastructure) 紧密集成。.NET 8 引入了许多新功能&#xff0c;如原生编译、值类型 (Value Types)、结构化并发 (structured concurrency) 和…

中铁建设集团集采网站张家界网站建设app

1.教程简介 本教程是YouTube大佬教程视频的随笔, 目前正在更新中... 教程地址[YouTube](https://www.youtube.com/watch?vXtQMytORBmM)2.安装 本教程使用的Unity版本 2021.3.34f1&#xff0c; 安装好该LTS(长期支持)版本之后, 在左侧Install选项卡Tab中选择对应版本右边的齿…

# 20232313 2025-2026-1 《网络与系统攻防技术》实验一实验报告 - 20232313

一、实验内容 学习通过以下三种方式利用pwn1程序的漏洞执行getShell函数:篡改程序流程——直接修改可执行文件,跳转至getShell; 栈溢出攻击——利用foo函数的缓冲区溢出漏洞,覆盖返回地址触发getShell; Shellcode…

完整教程:【无标题】

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

个人空间备案网站名称wordpress贴内幻灯片

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

vector使用中的一个小问题

定义一个二维的vector时,应该使用resize进行初始化,否则直接进行访问时会出错的。 C++中vector resize用法解析 - DeepSeek

一生一芯学习:PA2:输入输出

一生一芯学习:PA2:输入输出输入输出是计算机与外界交互的基本手段,只需要向设备发送一些有意义的数字信号,设备就会按照这些信号来工作。设备有自己的专属寄存器(如CPU的通用寄存器),也有自己的功能部件(如CPU…

深入解析:展会聚焦丨漫途科技亮相2025西北水务博览会!

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering() - 指南

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering() - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; d…

2025.10.7——2绿

普及+/提高- AT_agc031_b [AGC031B] Reversi 很简单的线性DP,很快就写出来了。 AT_abc406_f [ABC406F] Compare Tree Weights 树上的dfs序+树状数组,我被卡了好久……最后还因为树状数组写错功亏一篑了。

wordpress快站wordpress恢复边栏

问题描述&#xff0c;后台返回一个参数携带在url上面&#xff0c;发的时候是空格隔开的字符串&#xff0c;但是到了前端放到地址栏打开是一个号。 类似于 // 后台返回的url https://xxx.com?aaa bxxx // 打开浏览器后地址栏显示的 https://xxx.com?aaabxxx问了一下AI说是空…

完整教程:无人机避障——感知部分(Ubuntu 20.04 复现Vins Fusion跑数据集)胎教级教程

完整教程:无人机避障——感知部分(Ubuntu 20.04 复现Vins Fusion跑数据集)胎教级教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important…

姑苏区网站建设广州专业网站改版方案

企业们正在寻找新的方式来吸引和保持观众的注意力,一种新兴的解决方案就是使用Avatar虚拟形象技术&#xff0c;这种技术可以让用户在视频拍摄或直播场景中&#xff0c;以自定义的数字人形象出现&#xff0c;同时保持所有的表情和脸部驱动。美摄科技正是这个领域的领军者&#x…

我真的博了

其实标题指的是博弈论。 [AGC002E] Candy Piles 桌子上有 \(N\) 堆糖果。每堆糖果有 \(a_i\) 颗糖果。 Snuke 和 Ciel 正在玩游戏。他们轮流走。Snuke 先走。在每个回合中,当前玩家必须执行以下两个操作之一:选择剩余…

深入解析:人工智能-Chain of Thought Prompting(思维链提示,简称CoT)

深入解析:人工智能-Chain of Thought Prompting(思维链提示,简称CoT)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family:…

2025.10.6——1绿1蓝

普及+/提高- P3388 【模板】割点(割顶) Tarjan算法的模板题,但是代码不是我写的。 老师写的代码,有问题,我找出问题了。 提高+/省选- P1073 [NOIP 2009 提高组] 最优贸易 听完老师讲解后感觉这道题真的不难,很快…

红色网站呢网站备案查询 api

前言&#xff1a;预处理是我们的c语言源代码成为可执行程序的第一个步骤。而宏和预处理指令都是在这个阶段完成。本节内容就是关于宏和预处理指令相关知识点的解析。 目录 宏 预定义符号 #define定义常量 #define定义符号 #define定义宏 带副作用的宏参数 宏的替换规则…

深入解析:OpenCV CUDA模块图像处理------双边滤波的GPU版本函数bilateralFilter()

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …