区间 DP 详解

news2025/7/15 20:06:17

文章目录

  • 区间 DP
    • 分割型
    • 合并型
      • 环形合并

区间 DP

区间 DP,就是在对一段区间进行了若干次操作后的最小代价,一般是合并和拆分类型。

分割型

分割型,指把一个区间内的几项分开拆成一份一份的,再全部合起来就是当前答案,可以理解为合并型的另一种(合并型详见下面),它的时间复杂度一般为 O ( n 3 ) O(n^3) O(n3),其中我们一般设 dp[i][j] 表示把前 i i i 项拆成 j j j 份的最小值,而第三层循环则是循环的分割点,表示把前 i i i 项从 k k k 这里分开来看,这就是“分割”。由此,我们可以得到这样一个状态转移方程:

d p i , j = min ⁡ { d p i , j , d p k , j − 1 + 代价 } dp_{i,j}=\min\{dp_{i,j},dp_{k,j-1}+\text{代价}\} dpi,j=min{dpi,j,dpk,j1+代价}

当然,有时我们也会把这个 k k k 当做从 i − 1 i-1 i1 i i i 一共分成了 k k k 份,由此,我们可以得到另一种状态转移方程:

d p i , j = d p i − 1 , j − k + d p i , j dp_{i,j}=dp_{i-1,j-k}+dp_{i,j} dpi,j=dpi1,jk+dpi,j

这种情况下一般就不是讨论最小值,而是计数,我们可以看下面这道例题:

⼩明的花店新开张,为了吸引顾客,他想在花店的⻔⼝摆上⼀排花,共 m m m 盆。通过调查顾客的喜好,⼩明列出了顾客最喜欢的 n n n 种花,从 1 1 1 n n n 标号。为了在⻔⼝展出更多种花,规定第 i i i 种花不能超过 a i a_i ai 盆,摆花时同⼀种花放在⼀起,且不同种类的花需按标号的从⼩到⼤的顺序依次摆列。试编程计算,⼀共有多少种不同的摆花⽅案。

这就是我们刚刚说的第二种类型,直接套公式即可。注意初始化(初始化就不用我都说了吧,就是 d p i , 0 = 1 dp_{i,0}=1 dpi,0=1 呗),但这种类型很少见,我基本翻遍了全网才找到了这一道题,其余的基本都是第一种,所以各位同学终点记第一种就行,第二种做一个拓展。

AC 代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e6+7;
int n,m,a[106],dp[106][106];
signed main()
{
	cin>>n>>m;
	dp[0][0]=1;//初始化
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		dp[i][0]=1;
	}
	for(int i=1;i<=n;i++)//终点
	{
		for(int j=1;j<=m;j++)//分割份数
		{
			for(int k=0;k<=min(a[i],j);k++)//i-1 到 i 的分割份数
			{
				dp[i][j]=(dp[i][j]+dp[i-1][j-k])%mod;
			}
		}
	}
	cout<<dp[n][m];
	return 0;
}

下面留一道例题供大家练习:

今年是国际数学联盟确定的“2000――世界数学年”,⼜恰逢我国著名数学家华罗庚先⽣诞⾠ 90 周年。在华罗庚先⽣的家乡江苏⾦坛,组织了⼀场别开⽣⾯的数学智⼒竞赛的活动,你的⼀个好朋友 XZ 也有幸得以参加。活动中,主持⼈给所有参加活动的选⼿出了这样⼀道题⽬:

设有⼀个⻓度为 N N N 的数字串,要求选⼿使⽤ K K K 个乘号将它分成 K + 1 K+1 K+1 个部分,找出⼀种分法,使得这 K + 1 K+1 K+1 个部分的乘积能够为最⼤。

同时,为了帮助选⼿能够正确理解题意,主持⼈还举了如下的⼀个例⼦:

有⼀个数字串: 312 312 312, 当 N = 3 , K = 1 N=3,K=1 N=3,K=1 时会有以下两种分法:

  1. 3×12=36
  2. 31×2=62

这时,符合题⽬要求的结果是: 31 × 2 = 62 31\times2=62 31×2=62

现在,请你帮助你的好朋友 XZ 设计⼀个程序,求得正确的答案。

合并型

合并型,一般指把这一个区间内的相邻两项合在一起,每次代价为这两项的和,求最小代价。 这种题,我们只需要一个万能公式就可以搞定,它就是:

d p j , e d = min ⁡ { d p j , e d , d p j , k + d p k + 1 , e d + 代价 } dp_{j,ed}=\min\{dp_{j,ed},dp_{j,k}+dp_{k+1,ed}+\text{代价}\} dpj,ed=min{dpj,ed,dpj,k+dpk+1,ed+代价}

咳咳,不小心把祖传秘方给说出来了。

其中 j j j 是起点, e d ed ed 是终点, k k k 是分割点,表示从起点到终点中间一个把区间一分为二的点。这时再回去看看那个方程,是不是就明了多了?

这里我要说一下:这里我们一般写三层循环,最外面枚举区间长度,第二层枚举起点,第三层枚举分割点。所以时间复杂度也是 O ( n 3 ) O(n^3) O(n3)

还有就是 DP 的初始化我们一般都是这样:

for(int i=1;i<=n;i++)
{
	dp[i][i]=0;
}

表示你以当前这个点为起点同时为终点合并的代价为 0 0 0。当然,在不同的题中有不同的初始化,一般都是两个区间之间的代价等于多少这种。

为了让大家更好理解,我们拿一道例题来讲一讲(没有洛谷的可以看下面):

设有 N ( 0 ≤ N ≤ 300 ) N(0\le N\le300) N(0N300) 堆石子排成一排,其编号为 1 , 2 , 3 , … , N 1,2,3,\dots,N 1,2,3,,N。每堆石子有一定的质量 m i ( m i ≤ 1000 ) m_i(m_i\le1000) mi(mi1000)。现在要将这 N N N 堆石子合并成为一堆。每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻。合并时由于选择的顺序不同,合并的总代价也不相同。试找出一种合理的方法,使总的代价最小,并输出最小代价。

一道极其经典的合并型区间 DP,让我们套上上面的模版并把代价加入得(其中 s i s_i si m i m_i mi 的前缀和):

d p j , e d = min ⁡ { d p j , e d , d p j , k + d p k + 1 , e d + s e d − s j } dp_{j,ed}=\min\{dp_{j,ed},dp_{j,k}+dp_{k+1,ed}+s_{ed}-s_j\} dpj,ed=min{dpj,ed,dpj,k+dpk+1,ed+sedsj}

AC 记录

(代码自己写)。

环形合并

有时候,我们这个合并型可能会在一个环上合并,这时我们不好考虑首位合并的情况,所以就有一种办法:断环成链!我们只需要把这个环变成一条链,然后在后面再接上一次,就可以正常的跑合并型了,具体请看这张图:

[ a 1 , a 2 , a 3 , … , a n ] , a n + 1 , a n + 2 , … , a 2 n [a_1,a_2,a_3,\dots,a_n],a_{n+1},a_{n+2},\dots,a_{2n} [a1,a2,a3,,an],an+1,an+2,,a2n
a 1 , [ a 2 , a 3 , … , a n , a n + 1 ] , a n + 2 , … , a 2 n a_1,[a_2,a_3,\dots,a_n,a_{n+1}],a_{n+2},\dots,a_{2n} a1,[a2,a3,,an,an+1],an+2,,a2n
a 1 , a 2 , [ a 3 , … , a n , a n + 1 , a n + 2 ] , … , a 2 n a_1,a_2,[a_3,\dots,a_n,a_{n+1},a_{n+2}],\dots,a_{2n} a1,a2,[a3,,an,an+1,an+2],,a2n
⋯ \cdots
a 1 , a 2 , a 3 , … , a n , [ a n + 1 , a n + 2 , … , a 2 n ] a_1,a_2,a_3,\dots,a_n,[a_{n+1},a_{n+2},\dots,a_{2n}] a1,a2,a3,,an,[an+1,an+2,,a2n]

(有点抽象,但是因为设备太简陋了,也只能这样做。)

我们还是来看一道例题:

点我跳转至例题。

因为题目是一个 pdf 文件,不好取字,所以就把链接放在上面了,偷懒的同学也可以看下面的图片。

这就是一个很经典的环形区间 DP,所以我们可以先断环成链,然后在后面拼上一截,最后直接做区间合并型 DP 就行了。

但要注意的是这里的初始化不是 0 0 0,而是从 i − 1 i-1 i1 i + 1 i+1 i+1 的值为 ∏ k = i − 1 i + 1 a k \prod_{k=i-1}^{i+1}a_k k=i1i+1ak ∏ \prod 是多个数的乘积的意思)

AC 代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,mx,a[206],dp[206][206];//dp:从i到j的最大方案 
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		a[i+n]=a[i];//断环成链并拼上一节,方便后续处理
	}
	n*=2;
	for(int i=2;i<n;i++)//初始化
	{
		dp[i-1][i+1]=a[i-1]*a[i]*a[i+1];
	}
	for(int i=4;i<=n;i++)//长度 
	{
		for(int j=1;j<=n-i+1;j++)//起点 
		{
			int ed=i+j-1;
			for(int k=j+1;k<ed;k++)//分割点 
			{
				dp[j][ed]=max(dp[j][ed],dp[j][k]+dp[k][ed]+a[j]*a[k]*a[ed]);//这里注意:是 dp[j][k]+dp[k][ed] 而不是 dp[j][k]+dp[k+1][ed],具体原因大家自己想
			}
		}
	}
	n/=2;
	for(int i=1;i<=n;i++)
	{
		mx=max(mx,dp[i][i+n]);
	}
	cout<<mx;
	return 0;
}

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

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

相关文章

QAM 信号的距离以及能量归一化

QAM星座图平均功率能量_星座图功率计算-CSDN博客 正交幅度调制(QAM) - Vinson88 - 博客园 不同阶QAM调制星座图中&#xff0c;符号能量的归一化计算原理_qpsk的星座图归一化-CSDN博客 https://zhuanlan.zhihu.com/p/690157236

Reactive编程框架与工具

文章目录 6.2 后端 Reactive 框架6.2.1 Spring WebFlux核心架构核心组件实际应用高级特性性能优化适用场景与限制 6.2.2 Akka&#xff08;Actor模型&#xff09;Actor模型基础基本用法高级特性响应式特性实现性能优化实际应用场景优势与挑战 6.2.3 Vert.x&#xff08;事件驱动&…

Python爬虫第7节-requests库的高级用法

目录 前言 一、文件上传 二、Cookies 三、会话维持 四、SSL证书验证 五、代理设置 六、超时设置 七、身份认证 八、Prepared Request 前言 上一节&#xff0c;我们认识了requests库的基本用法&#xff0c;像发起GET、POST请求&#xff0c;以及了解Response对象是什么。…

Maven的安装配置-项目管理工具

各位看官&#xff0c;大家早安午安晚安呀~~~ 如果您觉得这篇文章对您有帮助的话 欢迎您一键三连&#xff0c;小编尽全力做到更好 欢迎您分享给更多人哦 今天我们来学习&#xff1a;Maven的安装配置-项目管理工具 目录 1.什么是Maven&#xff1f;Maven用来干什么的&#xff1f…

智能 SQL 优化工具 PawSQL 月度更新 | 2025年3月

&#x1f4cc; 更新速览 本月更新包含 21项功能增强 和 9项问题修复&#xff0c;重点提升SQL解析精度与优化建议覆盖率。 一、SQL解析能力扩展 ✨ 新增SQL语法解析支持 SELECT...INTO TABLE 语法解析&#xff08;3/26&#xff09; ALTER INDEX RENAME/VISIBLE 语句解析&#…

Ubuntu虚拟机编译安装部分OpenCV模块方法实现——保姆级教程

Ubuntu虚拟机的安装过程可以查看另一篇文章&#xff1a;VMware安装Ubuntu虚拟机实现COpenCV代码在虚拟机下运行教程-CSDN博客 目前我们已经下载好了OpenCV&#xff0c;这里以OpenCV4.5.2为例。 在内存要求尽可能小的情况下&#xff0c;可以尝试只编译安装代码中使用到的OpenC…

spring mvc @ResponseBody 注解转换为 JSON 的原理与实现详解

ResponseBody 注解转换为 JSON 的原理与实现详解 1. 核心作用 ResponseBody 是 Spring MVC 的一个注解&#xff0c;用于将方法返回的对象直接序列化为 HTTP 响应体&#xff08;如 JSON 或 XML&#xff09;&#xff0c;而不是通过视图解析器渲染为视图&#xff08;如 HTML&…

skynet.rawcall使用详解及应用场景

目录 核心特性函数原型使用场景场景 1&#xff1a;高性能二进制传输&#xff08;如文件转发&#xff09;场景 2&#xff1a;自定义序列化协议&#xff08;如 Protocol Buffers&#xff09;场景 3&#xff1a;跨服务共享内存&#xff08;避免拷贝&#xff09; 配套接收方实现与 …

使用SpringSecurity下,发生重定向异常

使用SpringSecurity下&#xff0c;发生空转异常 环境信息&#xff1a; Spring Boot 3.4.4 &#xff0c; jdk 17 &#xff0c; springSecurity 6.4.4 问题背景&#xff1a; 没有自定义controller &#xff0c;改写了login 页面&#xff0c;并且进行了成功后的跳转处理&#xf…

Elasticsearch | ES索引模板、索引和索引别名的创建与管理

关注&#xff1a;CodingTechWork 引言 在使用 Elasticsearch (ES) 和 Kibana 构建数据存储和分析系统时&#xff0c;索引模板、索引和索引别名的管理是关键步骤。本文将详细介绍如何通过 RESTful API 和 Kibana Dev Tools 创建索引模板、索引以及索引别名&#xff0c;并提供具…

力扣hot100_回溯(2)_python版本

一、39. 组合总和&#xff08;中等&#xff09; 代码&#xff1a; class Solution:def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:ans []path []def dfs(i: int, left: int) -> None:if left 0:# 找到一个合法组合ans.append(pa…

LPDDR4内存颗粒命名规则全解析:三星、镁光、海力士、南亚、长鑫等厂商型号解码与选型指南

由于之前DDR的系列选型文章有很好的反馈&#xff0c;所以补充LPDDR4低功耗内存的选型和命名规则&#xff0c;总结了目前市面上常用的内存&#xff0c;供硬件工程师及数码爱好者参考。 在智能手机、平板电脑和低功耗设备中&#xff0c;LPDDR4 SDRAM凭借其高带宽、低功耗特性成为…

【杂谈】Godot4.4导出到Android平台(正式导出)

学博而后可约&#xff0c;事历而后知要。 目录 一、准备二、Gradle构建三、配置Java SDK四、配置Android SDK五、配置密钥 一、准备 本文在前文【杂谈】Godot4.4导出到安卓平台&#xff08;调试导出&#xff09;的基础上&#xff0c;进行正式导出。调试导出并不是真正的编译导…

基于AI设计开发出来的业务系统是什么样的?没有菜单?没有表格?

基于AI设计开发出的业务系统仍然会包含菜单、表格等传统UI元素&#xff0c;但AI技术会显著改变它们的实现方式和交互逻辑。以下是具体分析&#xff1a; 一、传统元素的持续存在 功能刚需性 • 菜单承担着系统导航的核心功能&#xff0c;表格则是结构化数据展示的基础载体。根…

数字足迹管理(DFM):你的网络隐身指南

数字足迹管理&#xff08;DFM&#xff09;&#xff1a;你的网络隐身指南 ‌你可能不知道&#xff0c;你的姓名、电话、住址正在网上被“明码标价”‌ ——而这一切&#xff0c;可能只是因为你点过外卖、寄过快递&#xff0c;甚至注册过一个网站。 一、什么是数字足迹管理&#…

如何避免“过度承诺”导致的验收失败

如何避免“过度承诺”导致的验收失败&#xff1f;关键在于&#xff1a; 评估可行性、设置合理目标、高频沟通反馈、阶段性验收、做好风险管理。其中设置合理目标至关重要&#xff0c;很多团队往往在项目初期为迎合客户或领导而报出“最理想方案”&#xff0c;忽略了资源、技术及…

紧跟数字人热潮:123 数字人分身克隆系统源码部署与风口洞察

在当今数字化浪潮中&#xff0c;数字人技术无疑已成为最具活力与潜力的领域之一&#xff0c;正以迅猛之势席卷多个行业&#xff0c;重塑着人们的交互方式与商业运作模式。C 站作为技术交流的前沿阵地&#xff0c;汇聚了众多关注前沿科技的开发者与技术爱好者&#xff0c;今天来…

QT控件 修改QtTreePropertyBrowser自定义属性编辑器源码,添加第一列标题勾选,按钮,右键菜单事件等功能

头阵子遇到一个需要修改QtTreePropertyBrowser控件的需求&#xff0c;QT开发做这么久了&#xff0c;这个控件倒是第一次用&#xff0c;费了点时间研究&#xff0c;在这里做个简单的总结。 QtTreePropertyBrowser控件 是 Qt 解决方案 (Qt Solutions) 中的一个组件&#xff0c;用…

开源模型应用落地-模型上下文协议(MCP)-从数据孤岛到万物互联(一)

一、前言 当开发者还在为每个AI工具编写臃肿的API适配器时&#xff0c;一场关于「连接」的技术革命已悄然降临。模型上下文协议&#xff08;MCP&#xff09;正在用一套全新的交互语法&#xff0c;重新定义人工智能与物理世界的对话方式。MCP协议如同为AI系统装上了“万能接口”…

【区块链安全 | 第三十八篇】合约审计之获取私有数据(二)

文章目录 前言漏洞代码代码审计攻击步骤修复建议审计思路 前言 在【区块链安全 | 第三十七篇】合约审计之获取私有数据&#xff08;一&#xff09;中&#xff0c;介绍了私有数据、访问私有数据实例、Solidity 中的数据存储方式等知识&#xff0c;本文通过分析具体合约代码进行…