当前位置: 首页 > article >正文

区间dp(竞赛)

一、介绍

区间 dp 其实就是左右端点固定之后,用已经得出的小区间来更新大区间答案的 dp 方式。

非常重要的要素:小区间得到大区间,衍生出来的问题就是对于大区间如何划分成若干小区间,这直接决定了方程的书写。之后的例题中慢慢体会。

一般步骤:先固定长度 len,再固定左端点 i,右端点 j 自然固定。

边界条件是当 i == j 时,dp[i][j] = ...

二、例题

1、回文字串

P1435 [IOI 2000] 回文字串 - 洛谷

#include <bits/stdc++.h>
using namespace std;// dp[i][j]表示字符串在[i, j]中变成回文串最小插入数量
// s[i] == s[j]: dp[i][j] = dp[i + 1][j - 1];
// s[i] != s[j]: j == i + 1: dp[i][j] = 1;
//                     else: dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;
// i依赖i+1,j依赖j-1,所以顺序:i从大到小,j从小到大,且i <= j
// dp[n][n] = 0;
int dp[1010][1010];
int main()
{string s;cin >> s;int n = s.size();for(int i = n - 1; i >= 0; i--){for(int j = i; j < n; j++){if(i == j)dp[i][j] = 0;else if(i == j - 1){if(s[i] == s[j])dp[i][j] = 0;else dp[i][j] = 1;}else {if(s[i] == s[j])dp[i][j] = dp[i + 1][j - 1];else dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;}}}cout << dp[0][n - 1];return 0;
}

这道题由于 dp 表的含义,可以把 [i, j] 区域内的字符串看作已经是回文的,所以对于区间的划分只会在端点处,即 dp[i + 1][j] 和 dp[i][j - 1]

2、Treats for the Cows G/S

P2858 [USACO06FEB] Treats for the Cows G/S - 洛谷

#include <bits/stdc++.h>
using namespace std;const int N = 2010;
int a[N];
int dp[N][N];
// dp[i][j]表示在区间[i, j]中选出的最大价值
// 一定是小区间到大区间更新
// dp[i][j] = max(dp[i + 1][j] + x * a[i], dp[i][j - 1], x * a[j]);
// 区间dp顺序可以枚举长度加左端点,这样就能实现小区间到大区间
// 初始化:没有就全是0int main() 
{int n;cin >> n;for (int i = 1; i <= n; i++) cin >> a[i];for(int len = 1; len <= n; len++){for(int i = 1; i + len - 1 <= n; i++){int j = i + len - 1;int x = n - len + 1;dp[i][j] = max(dp[i + 1][j] + x * a[i], dp[i][j - 1] + x * a[j]);}}cout << dp[1][n];return 0;
}

这道题也是明确规定,你只能从两端取食物,所以分组还是端点处。

3、石子合并(弱化版)

P1775 石子合并(弱化版) - 洛谷

#include <bits/stdc++.h>
using namespace std;
int a[1010];
int n;
const int INF = 0x3f3f3f3f;
int dp[1010][1010];// dp[i][j]表示合并[i, j]区域的最小代价,所以是任意分成[i, k], [k + 1, j]的两组
// dp[i][j] = dp[i][k] + dp[k + 1][j];
// 初始化条件:i == j时,dp[i][j] = 0;
// 前缀和优化
int main()
{cin >> n;for(int i = 1; i <= n; i++){cin >> a[i];a[i] += a[i - 1];}for(int len = 2; len <= n; len++){for(int i = 1; i + len - 1 <= n; i++){int j = i + len - 1;dp[i][j] = INF;for(int k = i; k < j; k++)dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + a[j] - a[i - 1]);}}cout << dp[1][n];return 0;
}

这道题说的是你可以任意选择相邻的两个数进行合并,所以 dp[i][j] 的划分一定不能是只在端点处,而是要分成 dp[i][k], dp[k + 1][j] 两个区间。

4、石子合并

P1880 [NOI1995] 石子合并 - 洛谷

// 遇到环形问题可以数组复制,此时要明确起点和遍历长度
#include <bits/stdc++.h>
using namespace std;
int n;
int a[210];
int s[210];
int dp1[210][210];
int dp2[210][210];
const int INF = 0x3f3f3f3f;int main()
{cin >> n;for(int i = 1; i <= n; i++){cin >> a[i];a[i + n] = a[i];}for(int i = 1; i <= 2 * n; i++)s[i] = a[i] + s[i - 1];int ans1 = INF;int ans2 = -INF;for(int len = 2; len <= n; len++){for(int i = 1; len + i - 1 <= 2 * n; i++){int j = i + len - 1;dp1[i][j] = INF;for(int k = i; k < j; k++){dp1[i][j] = min(dp1[i][j], dp1[i][k] + dp1[k + 1][j] + s[j] - s[i - 1]);dp2[i][j] = max(dp2[i][j], dp2[i][k] + dp2[k + 1][j] + s[j] - s[i - 1]); if(len == n){ans1 = min(ans1, dp1[i][j]);ans2 = max(ans2, dp2[i][j]);}}}}cout << ans1 << endl;cout << ans2 << endl;return 0;
}

这道题思考方式和上一题一样,只不过是环形数组,对于环形数组,只要开两倍空间模拟线性,然后固定好长度 1 ~ n,固定好左端点 1 ~ 2 * n - len,遍历就没有任何问题。

5、248 G

P3146 [USACO16OPEN] 248 G - 洛谷

#include <bits/stdc++.h>
using namespace std;
int n;
int a[300];
int dp[300][300];// dp[i][j]表示[i, j]区域尝试合并之后的最大值,dp[i][j] == 0就代表区间不能合并
// 区域[i, j]被分成[i, k], [k + 1, j],如果二者相等且不是0,那就可以合并,不然dp[i][j]还是0,即不能合并
// 边界问题:i == j时区间可以合并,大小是a[i]
int main()
{cin >> n;for(int i = 1; i <= n; i++)cin >> a[i];int ans = 0;for(int len = 1; len <= n; len++){for(int i = 1; i + len - 1 <= n; i++){if(len == 1){dp[i][i] = a[i];ans = max(ans, dp[i][i]);}else {int j = i + len - 1;for(int k = i; k < j; k++){if(dp[i][k] == dp[k + 1][j] && dp[i][k] != 0){dp[i][j] = max(dp[i][j], dp[i][k] + 1);ans = max(ans, dp[i][j]);}}}}}cout << ans;return 0;
}

也是在区间里面任意找相邻且相等的数,所以分成 dp[i][k], dp[k + 1][j] 两个区间。

三、总结

所以理解用小区间更新大区间,自然而然就要想到如何正确的划分小区间也是非常重要的。

相关文章:

区间dp(竞赛)

一、介绍 区间 dp 其实就是左右端点固定之后&#xff0c;用已经得出的小区间来更新大区间答案的 dp 方式。 非常重要的要素&#xff1a;小区间得到大区间&#xff0c;衍生出来的问题就是对于大区间如何划分成若干小区间&#xff0c;这直接决定了方程的书写。之后的例题中慢慢…...

PySide6 GUI 学习笔记——常用类及控件使用方法(常用类颜色常量QColorConstants)

文章目录 一、概述二、颜色常量表标准 Qt 颜色SVG 颜色&#xff08;部分&#xff09; 三、Python 代码示例四、代码说明五、版本兼容性六、延伸阅读 一、概述 QColorConstants 是 Qt for Python 提供的一个预定义颜色常量集合&#xff0c;包含标准Qt颜色和SVG规范颜色。这些常…...

大模型技术演进与应用场景深度解析

摘要 本文系统梳理了当前主流大模型的技术架构演进路径,通过对比分析GPT、BERT等典型模型的创新突破,揭示大模型在参数规模、训练范式、应用适配等方面的核心差异。结合医疗、金融、教育等八大行业的实践案例,深入探讨大模型落地的技术挑战与解决方案,为从业者提供体系化的…...

鸿蒙5.0项目开发——鸿蒙天气项目的实现(主页1)

【高心星出品】 文章目录 页面效果&#xff1a;页面功能&#xff1a;页面执行流程&#xff1a;1. 页面初始化阶段2. 定位获取阶段3. 天气数据加载阶段 这个页面是整个天气应用的核心&#xff0c;集成了天气查询、定位、搜索等主要功能&#xff0c;提供了完整的天气信息服务。 …...

python项目参考文献

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

【ESP32】ESP-IDF开发 | 低功耗蓝牙开发 | GATT规范和ATT属性协议 + 电池电量服务例程

1. 简介 低功耗蓝牙中最为核心的部分当属 GATT&#xff08;Generic Attribute Profile&#xff09;&#xff0c;全称通用属性配置文件。而 GATT 又是建立在 ATT 协议&#xff08;属性协议&#xff09;的基础之上&#xff0c;为 ATT 协议传输和存储的数据建立了通用操作和框架。…...

2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题

2025 年九江市第二十三届中职学校技能大赛 &#xff08;网络安全&#xff09;赛项竞赛样题 &#xff08;二&#xff09;A 模块基础设施设置/安全加固&#xff08;200 分&#xff09;A-1 任务一登录安全加固&#xff08;Windows,Linux&#xff09;A-2 任务二 Nginx 安全策略&…...

【记录】Windows|竖屏怎么调整分辨率使横竖双屏互动鼠标丝滑

本文版本&#xff1a;Windows11&#xff0c;记录一下&#xff0c;我最后调整的比较舒适的分辨率是800*1280。 文章目录 第一步 回到桌面第二步 右键桌面第三步 设置横屏为主显示器第四步 调整分辨率使之符合你的需求第五步 勾选轻松在显示器之间移动光标第六步 拖动屏幕符合物理…...

开源项目实战学习之YOLO11:12.2 ultralytics-models-sam-decoders.py源码分析

👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-decoders.pyblocks.py: 定义模型中的各…...

数据结构*优先级队列(堆)

什么是优先级队列(堆) 优先级队列一般通过堆&#xff08;Heap&#xff09;这种数据结构来实现&#xff0c;堆是一种特殊的完全二叉树&#xff0c;其每个节点都满足堆的性质。如下图所示就是一个堆&#xff1a; 堆的存储方式 由于堆是一棵完全二叉树&#xff0c;所以也满足二…...

汽车Wafer连接器:工业设备神经网络的隐形革命者

汽车Wafer连接器正在突破传统车载场景的边界&#xff0c;以毫米级精密结构重构工业设备的连接范式。这款厚度不足3毫米的超薄连接器&#xff0c;在新能源电池模组中承载200A持续电流的同时&#xff0c;仍能保持85℃温升的稳定表现&#xff0c;其每平方厘米高达120针的触点密度&…...

微信小程序:封装表格组件并引用

一、效果 封装表格组件,在父页面中展示表格组件并显示数据 二、表格组件 1、创建页面 创建一个components文件夹,专门用于存储组件的文件夹 创建Table表格组件 2、视图层 (1)表头数据 这里会从父组件中传递表头数据,这里为columns,后续会讲解数据由来 循环表头数组,…...

湖北理元理律师事务所:债务优化中的双维支持实践解析

在债务压力与生活质量失衡的社会议题下&#xff0c;法律服务机构的功能边界正在从单一的法律咨询向复合型支持延伸。湖北理元理律师事务所通过“法律心理”双维服务模式&#xff0c;探索债务优化与生活保障的平衡路径&#xff0c;其方法论或为行业提供实践参考。 法律框架&…...

uniapp在APP上如何使用websocket--详解

UniApp 在 APP 端如何使用 WebSocket以及常见问题 一、WebSocket 基础概念 WebSocket 是一种在单个TCP连接上进行全双工通信的协议&#xff0c;适用于实时数据传输场景&#xff08;如聊天室、实时游戏、股票行情等&#xff09;。 与传统HTTP对比 特性WebSocketHTTP连接方式…...

计网| 网际控制报文协议(ICMP)

目录 网际控制报文协议&#xff08;ICMP&#xff09; 一、ICMP 基础特性 二、ICMP 报文分类及作用 差错报告报文 询问报文 网际控制报文协议&#xff08;ICMP&#xff09; ICMP&#xff08;Internet Control Message Protocol&#xff0c;网际控制报文协议&#xff09;是 …...

Conda 完全指南:从环境管理到工具集成

Conda 完全指南&#xff1a;从环境管理到工具集成 在数据科学、机器学习和 Python 开发领域&#xff0c;环境管理一直是令人头疼的问题。不同项目依赖的库版本冲突、Python 解释器版本不兼容等问题频繁出现&#xff0c;而 Conda 的出现彻底解决了这些痛点。作为目前最流行的跨…...

安卓中0dp和match_parent区别

安卓中的 0dp 和 match_parent 的区别&#xff1f; 第一章 前言 有段时间&#xff0c;看到同事在编写代码的时候&#xff0c;写到的是 0dp 有时候自己写代码的时候&#xff0c;编写的是 match_parent 发现有时候效果很类似。 后来通过一个需求案例&#xff0c;才发现两者有着…...

蓝桥杯-不完整的算式

问题描述 小蓝在黑板上写了一个形如 AopBCAopBC 的算式&#xff0c;其中 AA、BB、CC 都是非负整数&#xff0c;opop 是 、-、*、/、-、*、/&#xff08;整除&#xff09;四种运算之一。不过 AA、opop、BB、CC 这四部分有一部分被不小心的同学擦掉了。 给出这个不完整的算式&a…...

信贷风控笔记4——贷前策略之额度、定价(面试准备12)

1.贷前模型的策略应用 分类&#xff1a;审批准入&#xff08;对头尾部区分度要求高&#xff09;&#xff1a;单一规则&#xff08;找lift>3的分数做规则&#xff09;&#xff1b;二维交叉&#xff1b;拒绝回捞 额度定价&#xff08;对排序性要求高&#xff09;&am…...

A级、B级弱电机房数据中心建设运营汇报方案

该方案围绕A 级、B 级弱电机房数据中心建设与运营展开,依据《数据中心设计规范》等标准,施工范围涵盖 10 类机房及配套设施,采用专业化施工团队与物资调配体系,强调标签规范、线缆隐藏等细节管理。运营阶段建立三方协同运维模式,针对三级故障制定30 分钟至 1 小时响应机制…...

Linux中的域名解析服务器

一、DNS&#xff08;域名系统&#xff09;详解 1. 核心功能与特点 特性说明核心作用将域名&#xff08;如 www.example.com&#xff09;转换为 IP 地址&#xff08;如 192.168.1.1&#xff09;&#xff0c;实现人类可读地址与机器可读地址的映射。端口与协议- 默认端口&#…...

如何优化Java中十进制字符串转十六进制的性能

在 Java 中优化十进制字符串转十六进制的性能&#xff0c;可以从减少对象创建、避免正则表达式、使用高效数据结构等方面入手。以下是具体的优化方案&#xff1a; 1. 避免字符串分割&#xff0c;直接遍历字符数组 原始方法&#xff08;频繁创建子字符串&#xff09;&#xff1…...

CycleISP: Real Image Restoration via Improved Data Synthesis通过改进数据合成实现真实图像恢复

摘要 大规模数据集的可用性极大释放了深度卷积神经网络(CNN)的潜力。然而,针对单图像去噪问题,获取真实数据集成本高昂且流程繁琐。因此,图像去噪算法主要基于合成数据开发与评估,这些数据通常通过广泛假设的加性高斯白噪声(AWGN)生成。尽管CNN在合成数据集上表现优异…...

Day28 Python打卡训练营

知识点回顾&#xff1a; 1. 类的定义 2. pass占位语句 3. 类的初始化方法 4. 类的普通方法 5. 类的继承&#xff1a;属性的继承、方法的继承 作业 题目1&#xff1a;定义圆&#xff08;Circle&#xff09;类 要求&#xff1a; 1. 包含属性&#xff1a;半径 radius。 2. …...

【OpenCV】基本数据类型及常见图像模式

是什么&#xff1f;能做什么&#xff1f;解决什么问题&#xff1f;为什么用它&#xff1f; OpenCV:是一个基于开源发行的跨平台计算机视觉库&#xff0c;实现 一、应用场景&#xff1a; 目标识别&#xff1a;人脸、车辆、车牌...自动驾驶医学影像分析视频内容理解与分析&…...

Linux之Nginx安装及配置原理篇(一)

Nginx安装及配置 前情回顾 首先针对Nginx进程模型&#xff0c;我们回顾一下它的原理机制&#xff0c;我们知道它是通过Master通过fork分发任务节点给予work节点&#xff0c;然后work节点触发了event事件&#xff0c;之后通过一个access_muttex互斥锁&#xff0c;来单线程调用我…...

【Linux网络】NAT和代理服务

NAT 之前我们讨论了&#xff0c;IPv4协议中&#xff0c;IP地址数量不充足的问题。 原始报文途径路由器WAN口时&#xff0c;对报文中的源IP进行替换的过程&#xff0c;叫做NAT。 NAT技术当前解决IP地址不够用的主要手段&#xff0c;是路由器的一个重要功能&#xff1a; NAT能…...

中药药效成分群的合成生物学研究进展-文献精读130

Advances in synthetic biology for producing potent pharmaceutical ingredients of traditional Chinese medicine 中药药效成分群的合成生物学研究进展 摘要 中药是中华民族的文化瑰宝&#xff0c;也是我国在新药创制领域的重要驱动力。许多中药材来源于稀缺物种&#xf…...

【消息队列】RabbitMQ基本认识

目录 一、基本概念 1. 生产者&#xff08;Producer&#xff09; 2. 消费者&#xff08;Consumer&#xff09; 3. 队列&#xff08;Queue&#xff09; 4. 交换器&#xff08;Exchange&#xff09; 5. 绑定&#xff08;Binding&#xff09; 6. 路由键&#xff08;Routing …...

OCCT知识笔记之OCAF框架详解

OCAF框架在OCCT项目中的构建与使用指南 Open CASCADE Application Framework (OCAF)是Open CASCADE Technology (OCCT)中用于管理CAD数据的核心框架&#xff0c;它提供了一种结构化方式来组织和管理复杂的CAD数据&#xff0c;如装配体、形状、属性(颜色、材料)和元数据等。本文…...