acwing算法基础之动态规划--线性DP和区间DP
目录
- 1 基础知识
- 2 模板
- 3 工程化
1 基础知识
线性DP:状态转移表达式存在明显的线性关系。
区间DP:与顺序有关,状态与区间有关。
2 模板
3 工程化
题目1:数字三角形。
解题思路:直接DP即可,f[i][j]
可以来自f[i-1][j] + a[i][j]
和f[i-1][j-1] + a[i][j]
,注意f[i-1][j]
不存在的情况(最后一个点)和f[i-1][j-1]
不存在的情况(第一个点)。
C++代码如下,
#include <iostream>using namespace std;const int N = 510;
int n;
int a[N][N];
int f[N][N];int main() {cin >> n;for (int i = 0; i < n; ++i) {for (int j = 0; j < i + 1; ++j) {cin >> a[i][j];}}for (int i = 0; i < N; ++i) {for (int j = 0; j < N; ++j) {f[i][j] = -0x3f3f3f3f;}}f[0][0] = a[0][0];for (int i = 1; i < n; ++i) {for (int j = 0; j < i + 1; ++j) {f[i][j] = max(f[i][j], f[i-1][j] + a[i][j]);if (j - 1 >= 0) f[i][j] = max(f[i][j], f[i-1][j-1] + a[i][j]);}}int res = -0x3f3f3f3f;for (int j = 0; j < n; ++j) res = max(res, f[n-1][j]);cout << res << endl;return 0;
}
题目2:最长上升子序列。注意可以连续,比如3 1 2 1 8 5 6
,那么它的最长上升子序列为1 2 5 6
,长度为4。
解题思路:DP即可。
状态定义,f[i]
表示以第 i i i元素结尾的上升子序列的最大长度。
状态转移,有,
- 没有上一个元素,即
f[i] = 1
。 - 从第 i − 1 i-1 i−1个元素转移过来,需要满足
a[i-1] < a[i]
,则f[i-1] + 1
。 - 从第 i − 2 i-2 i−2个元素转移过来,需要满足
a[i-2] < a[i]
,则f[i-2] + 1
。
…… - 从第 0 0 0个元素转移过来,需要满足
a[0] < a[i]
,则f[0] + 1
。
C++代码如下,
#include <iostream>using namespace std;const int N = 1010;
int n;
int a[N];
int f[N];int main() {cin >> n;for (int i = 0; i < n; ++i) cin >> a[i];for (int i = 0; i < n; ++i) {f[i] = 1;for (int j = 0; j < i; ++j) {if (a[j] < a[i]) f[i] = max(f[i], f[j] + 1);} }int res = 0;for (int i = 0; i < n; ++i) res = max(res, f[i]);cout << res << endl;return 0;
}
同时输出最长上升子序列,那么此时只需要记住当前状态是从哪一个状态转移过来的,然后逆序输出即可。C++代码如下,
#include <iostream>
#include <algorithm>using namespace std;const int N = 1010;
int n;
int a[N];
int f[N];
int g[N];int main() {cin >> n;for (int i = 0; i < n; ++i) cin >> a[i];for (int i = 0; i < n; ++i) {f[i] = 1;g[i] = -1; //g[i]=-1表示它是子序列的起点for (int j = 0; j < i; ++j) {if (a[j] < a[i]) {if (f[i] < f[j] + 1) {f[i] = f[j] + 1;g[i] = j;//g[i]=j表示状态f[i]是从状态f[j]转移过来的}}} }int res = 0;for (int i = 0; i < n; ++i) {if (f[i] > f[res]) {res = i;}}cout << f[res] << endl;//输出最长子序列的长度vector<int> ans; //最长子序列for (int i = res; i != -1; i = g[i]) {ans.emplace_back(a[i]);}reverse(ans.begin(), ans.end());for (int i = 0; i < ans.size(); ++i) cout << ans[i] << " ";cout << endl;return 0;
}
测试样例,
输入:
7
3 1 2 1 8 5 6
输出:
4
1 2 5 6
题目3:最长公共子序列,给定字符串a和字符串b,求它们的最长公共子序列。例如acbd
和abedc
,则它们的最长公共子序列为abd
,长度为3。
思路:利用DP来求解,由于这里求的是最大长度,因此在状态转移时,可以适当放大,以便可以表示相应转移路径。
状态定义,f[i][j]
:从字符串a前i个中选且从字符串b中前j个中选的公共子序列的最大长度。
状态转移,有,
- a[i]不在最优公共子序列当中,b[j]不在最优公共子序列当中,则
f[i-1][j-1]
。 - a[i]在最优公共子序列当中,b[j]不在最优公共子序列当中,无法表示???,故将其放大,为
f[i][j-1]
。 - a[i]不在最优公共子序列当中,b[j]在最优公共子序列当中,无法表示???,故将其放大,为
f[i-1][j]
。 - a[i]在最优公共子序列当中,b[j]在最优公共子序列当中,要求
a[i]=b[j]
,则f[i-1][j-1] + 1
。
进一步思考,由于进行了放大,因此第(2)种情况和第(3)种情况包含了第(1)种情况。因此在代码实现时,可以考虑如下状态转移f[i][j-1]
、f[i-1][j]
和f[i-1][j-1] + 1
。
C++代码如下,
#include <iostream>using namespace std;const int N = 1010;
char a[N], b[N];
int n, m;
int f[N][N];int main() {cin >> n >> m;cin >> a + 1 >> b + 1;for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {f[i][j] = max(f[i-1][j], f[i][j-1]);if (a[i] == b[j]) f[i][j] = max(f[i][j], f[i-1][j-1] + 1);}}cout << f[n][m] << endl;return 0;
}
题目4:合并相邻石子的最小代价。例如1 3 5 2
,合并前两堆石子1
和3
的代价是4,得到4 5 2
。
解题思路:区间合并类DP,状态定义围绕着区间,然后怎么层层递进计算状态,比较考验。答案是枚举区间长度来计算。
状态定义,f[i][j]
:合并第i~j堆石子的最小代价。
状态转移,有,
- 最后一次合并为[i,i]和[i+1,j]这两个区间合并,即
f[i][i] + f[i + 1][j] + s[j] - s[i - 1]
,其中s[i]
表示前缀和。 - 最后一次合并为[i,i+1]和[i+2,j]这两个区间合并,即
f[i][i + 1] + f[i + 2][j] + s[j] - s[i - 1]
。 - 最后一次合并为[i,i+2]和[i+3,j]这两个区间合并,即
f[i][i + 2] + f[i + 3][j] + s[j] - s[i - 1]
。
…… - 最后一次合并为[i,j-1]和[j,j]这两个区间合并,即
f[i][j - 1] + f[j][j] + s[j] - s[i - 1]
。
初始化,f[i][i]=0
,然后其余初始化为正无穷大,比如1e9
。
最终答案为,f[1][n]
。
注意状态的遍历,是通过区间长度从1到n实现的。
C++代码如下,
#include <iostream>using namespace std;const int N = 310;
int a[N];
int s[N];
int f[N][N];
int n;int main() {cin >> n;for (int i = 1; i <= n; ++i) cin >> a[i];for (int i = 1; i <= n; ++i) s[i] += s[i-1] + a[i];for (int len = 2; len <= n; ++len) {//枚举左端点for (int i = 0; i + len - 1 <= n; ++i) {int l = i, r = i + len - 1;f[l][r] = 1e9;for (int k = l; k < r; ++k) {f[l][r] = min(f[l][r], f[l][k] + f[k+1][r] + s[r] - s[l-1]);}}}cout << f[1][n] << endl;return 0;
}
相关文章:
acwing算法基础之动态规划--线性DP和区间DP
目录 1 基础知识2 模板3 工程化 1 基础知识 线性DP:状态转移表达式存在明显的线性关系。 区间DP:与顺序有关,状态与区间有关。 2 模板 3 工程化 题目1:数字三角形。 解题思路:直接DP即可,f[i][j]可以来…...

力扣 622.设计循环队列
目录 1.解题思路2.代码实现 1.解题思路 首先,该题是设计循环队列,因此我们有两种实现方法,即数组和链表,但具体考虑后,发现数组实现要更容易一些,因此使用数组实现,因此我们要给出头和尾变量&a…...

初识Linux(2).妈妈再也不用担心我Linux找不到门了。
文章目录 前言 1.man指令(重要):例如: 2.cp指令(重要):例如:把123.txt复制到a目录中类似window如下操作: 3.mv例如:类似window如下操作: 4.nano例…...

房屋租赁出售经纪人入驻小程序平台
一款专为房屋中介开发的小程序平台,支持独立部署,源码交付,数据安全无忧。 核心功能:房屋出租、经纪人独立后台、分佣后台、楼盘展示、房型展示、在线咨询、地址位置配套设施展示。 程序已被很多房屋交易中介体验使用过&#x…...

【计算方法与科学建模】矩阵特征值与特征向量的计算(五):乘幂法的加速(带有原点移位的乘幂法)
文章目录 一、Jacobi 旋转法二、Jacobi 过关法三、Householder 方法四、乘幂法四、乘幂法的加速 矩阵的特征值(eigenvalue)和特征向量(eigenvector)在很多应用中都具有重要的数学和物理意义。 本文将详细介绍乘幂法的基本原理和步…...

2023年【起重机械指挥】考试题库及起重机械指挥考试资料
题库来源:安全生产模拟考试一点通公众号小程序 2023年【起重机械指挥】考试题库及起重机械指挥考试资料,包含起重机械指挥考试题库答案和解析及起重机械指挥考试资料练习。安全生产模拟考试一点通结合国家起重机械指挥考试最新大纲及起重机械指挥考试真…...
GoLang语言范围(Range)
目录 一、在数组、切片上使用‘range’ 二、在映射上使用range 三、在通道上使用range Go语言中的range关键字用于迭代数组(数组、切片、字符串)、映射(map)、通道(channel)或者在 for 循环中迭代每一个…...

汽车电子 -- 车载ADAS之FCW(前方碰撞预警)
相关法规文件: FCW: GB∕T 33577-2017 智能运输系统 车辆前向碰撞预警系统 性能要求和测试规程 一、前方碰撞预警 FCW( Forward Collision Warning) 参看:法规标准-GB/T 33577标准解读(2017版) 1、状态机 系统关闭 当车辆前向碰撞预警系…...

爬虫系统Docker和Kubernetes部署运维最佳实践
在构建和管理爬虫系统时,使用Docker和Kubernetes可以带来诸多好处,如方便的部署、弹性伸缩和高可靠性。然而,正确的部署和运维实践对于确保系统稳定运行至关重要。在本文中,我将分享爬虫系统在Docker和Kubernetes上的最佳部署和运…...
音视频5、libavformat-1
libavformat库,是FFmpeg中用于处理各种媒体容器格式(media container format)的库。它的两个最主要的功能是 : demuxing:解封装,将一个媒体文件分割为多个多媒体流 muxing:封装,将多个多媒体数据流写入到指定媒体容器格式的文件中 这两个过程所做的…...

【数据结构复习之路】树和二叉树(严蔚敏版)万字详解主打基础
专栏:数据结构复习之路 复习完上面四章【线性表】【栈和队列】【串】【数组和广义表】,我们接着复习 树和二叉树,这篇文章我写的非常详细且通俗易懂,看完保证会带给你不一样的收获。如果对你有帮助,看在我这么辛苦整理…...
nginx使用详解:转发规则、负载均衡、server_name
文章目录 一、nginx常用的转发规则location 指令说明location转发使用 二、upstream负载均衡使用三、server_name使用四、其他常用配置限制请求类型处理静态资源目录遍历问题限制客户端使用的ip或者域名 五、需要注意的地方location /api1 探讨location ~ /api1 探讨࿰…...

HarmonyOS 数据持久化 Preferences 如何在页面中对数据进行读写
背景介绍 最近在了解并跟着官方文档尝试做一个鸿蒙app 小demo的过程中对在app中保存数据遇到些问题 特此记录下来 这里的数据持久化以 Preferences为例子展开 废话不多说 这里直接上节目(官方提供的文档示例:) 以Stage模型为例 1.明确preferences的类型 import data_prefer…...

ESP32-Web-Server编程- JS 基础 4
ESP32-Web-Server编程- JS 基础 4 概述 HTML 内联事件处理器,你永远不应该使用 HTML 事件处理器属性——因为那些已经过时了,使用它们是不好的做法。 在前端编程中,除了将期望发生的事件写为 JS 文件外,还可以使用一些组件自带…...
JAVA的反射机制
什么是反射机制 Java反射机制是指在运行时动态地获取类的信息并操作类的成员(属性、方法、构造方法等)的能力。通过反射,我们可以解析出类的完整信息,包括构造函数、成员变量、继承关系等。以下是一个使用反射机制创建对象、调用…...

Couchdb 权限绕过漏洞复现(CVE-2017-12635)
Couchdb 权限绕过漏洞复现(CVE-2017-12635) 开启环境给了三个端口号,不知道哪个是正常的,最后试出来52226端口正常。 登录URL:http://192.168.91.129:52226/_utils/# 来到了登录页面 用postman发送PUT…...
GZ031 应用软件系统开发赛题第2套
2023年全国职业院校技能大赛 应用软件系统开发赛项(高职组) 赛题第2套 工位号: 2023年4月 竞赛说明 一、项目背景 党的二十大报告指出,要加快建设制造强国、数字中国,推动制造业高端化、智能化、…...

lack——主页前后端开发优化(精华:java多线程实现数据插入)
lack——主页前后端开发优化 前端开发主页 最容易的方式:list列表<template><van-cardv-for"user in props.userList":desc"user.profile":title"${user.username} (${user.planetCode})":thumb"user.avatarUrl"…...
Anaconda深度学习环境配置命令参考
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Anaconda深度学习环境配置 Anaconda 管理1. 检查 Anaconda 版本2. 获取版本号3. 列出所有的虚拟环境4. 查看环境管理的全部命令帮助5. conda升级6. conda升级后释放空间 Anac…...

【iOS】知乎日报
文章目录 前言一、首页1.网络的异步请求2.避免同一网络请求执行多次3.下拉刷新与上拉加载的实现下拉刷新上拉加载 二、网页1.webView的实现2.webView的滑动加载3.网页与首页内容的同步更新 三、评论区Masonory实现行高自适应 四、收藏中心通过FMDB实现数据持久化1.创建或打开数…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...