动态规划基础

article/2025/7/30 4:58:47

动态规划是一种算法思想,关键是理解思想和什么时候用。

算法思想

动态规划用于解决多阶段决策最优化问题,这类问题类似递推。

1.阶段

将问题分为多个阶段,每个阶段之间有联系,即可递推。一般可按问题求解次序或问题的递归性质划分阶段。

2.状态

确定阶段是为了更明确状态,状态是当前阶段的具体内容,即“位置”和当前“位置”的值,做题时可先将状态定义成阶段,发现记录内容不足时,可修改状态定义,或增加状态维度。

3.决策

即当前状态可做出的选择。

4.状态转移方程

确定了状态和决策,即可确定状态转移方程,状态明确要求什么,决策确定如何转移(递推),根据当前状态如何求出写出状态转移方程。

5.边界

边界即递推起点,根据状态转移方程确定。

6.目标解

明确状态定义,即可根据定义确定目标解。

确定以上六点即可解出动规题。

什么时候用动规

动规三要素

1.最优子结构性质

即当前阶段的最优解可由之前阶段的子问题最优解推导出来。能用动规的问题一定有最优子结构性质。

2.重叠子问题

即不同状态存在相同的子问题。

动规通过dp数组记录状态,使得每个子问题只计算一次,大大提高有重叠子问题性质的问题的求解速度,虽不是动规解决的问题的必要性质,但若没有这个性质,动规和别的算法的时间复杂度差不多。

3.无后效性

无后效性是指当前阶段的每个问题的解一旦确定,就不会再被更改。动规解决的问题一定是无后效性的。

可通过判断将可转移的状态间连一条有向边后形成的有向图是否无环来判断是否是无后效性的。

问题符合如上三个要素即可用动规解决。

实现

1.for循环遍历顺序

根据状态转移方程的推导顺序(先求什么,再求什么)确定遍历顺序。

2.空间优化

dp数组只记录可推导出后续问题的问题和结果,其他不做记录。

输入数据若不需复用或存储(有的问题必须存储输入数据,后续算法才能正常进行),则直接用变量接住输入,不开数组。

题目

OpenJudge 9267:核电站

OpenJudge - 9267:核电站

通过求解的先后次序划分阶段,代码如下:

#include <iostream>
#include <cmath>
using namespace std;typedef long long LL;const LL Maxn = 50 + 5;
const LL Maxm = 5 + 5;LL dp[Maxn][Maxm];int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);LL n, m;cin >> n >> m;dp[1][1] = 1, dp[1][0] = 1;for (LL i = 2; i <= n; ++i) {dp[i][0] += dp[i - 1][0];for (LL j = 1; j <= min(i, m - 1); ++j) {dp[i][j] += dp[i - 1][j - 1];dp[i][0] += dp[i - 1][j];}}LL res = 0;for (LL j = 0; j <= min(n, m - 1); ++j)  res += dp[n][j];cout << res;return 0;
}

OpenJudge 1759:最长上升子序列

OpenJudge - 1759:最长上升子序列

先将状态定义成阶段,发现不足,在修改。

方法一:增加状态维度

#include <iostream>
#include <cmath>
using namespace std;typedef long long LL;const LL Maxn = 1000 + 5;LL vct[Maxn], dp[Maxn][2];int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);LL n;cin >> n;for (LL i = 1; i <= n; ++i)  cin >> vct[i];for (LL i = 1; i <= n; ++i) {dp[i][0] = 0;dp[i][1] = 1;for (LL j = 1; j < i; ++j) {if (vct[j] < vct[i])  dp[i][1] = max(dp[i][1], dp[j][1] + 1);dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);}}cout << max(dp[n][0], dp[n][1]);return 0;
}

方法二:适当修改状态定义

#include <iostream>
#include <cmath>
using namespace std;typedef long long LL;const LL Maxn = 1000 + 5;LL vct[Maxn], dp[Maxn];int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);LL n, res = 0;cin >> n;for (LL i = 1; i <= n; ++i)  cin >> vct[i];for (LL i = 1; i <= n; ++i) {dp[i] = 1;for (LL j = 1; j < i; ++j) {if (vct[j] < vct[i])  dp[i] = max(dp[i], dp[j] + 1);}res = max(res, dp[i]);}cout << res;return 0;
}

OpenJudge 1808:公共子序列

OpenJudge - 1808:公共子序列

状态定义为阶段。

因为是多组数据,注意每个数组的初始化情况。

#include <iostream>
#include <cmath>
using namespace std;typedef long long LL;const LL Maxn = 200 + 5;LL dp[Maxn][Maxn];int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);string str1, str2;while (cin >> str1 >> str2) {for (LL i = 0; i <= str2.size(); ++i)  dp[0][i] = 0;for (LL i = 1; i <= str1.size(); ++i) {dp[i][0] = 0;for (LL j = 1; j <= str2.size(); ++j) {dp[i][j] = 0;if (str1[i - 1] == str2[j - 1])  dp[i][j] = dp[i - 1][j - 1] + 1;else  dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}}cout << dp[str1.size()][str2.size()] << '\n';}return 0;
}

OpenJudge 2989:糖果

OpenJudge - 2989:糖果

明确什么状态能求出当前状态。

注意dp初始化,dp[0][j] = LONG_MIN(不是0,j = 1~(k-1)),dp[0][0] = 0,不然结果是15,会加上无解情况。

最值问题,无解状态设为无限小(大),使得有解状态一定不从无解状态推导出来。

#include <iostream>
#include <climits>#include <cmath>
using namespace std;typedef long long LL;const LL Maxn = 100 + 5;
const LL Maxk = 100 + 5;LL dp[Maxn][Maxk - 1];int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);LL n, k, x;cin >> n >> k;dp[0][0] = 0;for (LL j = 1; j < k; ++j)  dp[0][j] = LONG_MIN;for (LL i = 1; i <= n; ++i) {cin >> x;for (LL j = 0; j < k; ++j)dp[i][j] = max(dp[i - 1][j], dp[i - 1][((j - x) % k + k) % k] + x);}cout << (dp[n][0] <= 0 ? 0 : dp[n][0]);return 0;
}

洛谷 P2066 机器分配

#include <iostream>
#include <cmath>
using namespace std;typedef long long LL;const LL Maxn = 10 + 5;
const LL Maxm = 15 + 5;LL vct[Maxn][Maxm], dp[Maxn][Maxm], Res[Maxn][Maxm];void dfs(LL x, LL y) {if (x == 0)  return;dfs(x - 1, y - Res[x][y]);cout << x << ' ' << Res[x][y] << '\n';
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);LL n, m;cin >> n >> m;for (LL i = 1; i <= n; ++i) {for (LL j = 1; j <= m; ++j)cin >> vct[i][j];}for (LL i = 1; i <= n; ++i)for (LL j = 1; j <= m; ++j)for (LL k = 0; k <= j; ++k) {if (dp[i][j] <= dp[i - 1][j - k] + vct[i][k]) {dp[i][j] = dp[i - 1][j - k] + vct[i][k];Res[i][j] = k;}}cout << dp[n][m] << '\n';dfs(n, m);return 0;
}


http://www.hkcw.cn/article/rYanWaccsh.shtml

相关文章

WEB3——什么是ABI

怎么获得ABI&#xff1f; 在编译完合约后&#xff0c;可以在左边下面点击复制ABI ABI&#xff08;Application Binary Interface&#xff0c;应用二进制接口&#xff09;是用来让前端或服务端 JavaScript 代码与智能合约进行交互的桥梁&#xff0c;它描述了合约的函数、事件和…

本地部署Ollama DeepSeek-R1:8B,接入Cherry Studio

本地部署Ollama DeepSeek-R1:8B&#xff0c;接入Cherry Studio 本教程为本地部署ollama 环境&#xff0c;运行deepseek-r1:8B 模型&#xff0c;并完成cherry studio接入调用。 实现无网环境也可提问模型 一、ollama 环境安装 通过网盘分享的文件&#xff1a;OllamaSetup.ex…

彻底解决Win11文件资源管理器预览窗格无法预览问题

国内某几个流氓软件&#xff08;W*S、*狗PDF...&#xff09;&#xff0c;耗子尾之&#xff01;&#xff01;&#xff01; &#xff08;转载&#xff09;Windows中PDF TXT Excel Word PPT等Office文件在预览窗格无法预览的终级解决方法大全 https://zhuanlan.zhihu.com/p/4542…

竞争加剧,美团的战略升维:反内卷、科技与全球化

5月26日&#xff0c;美团发布2025年第一季度业绩报告&#xff0c;交出了一份兼具韧性与创新性的成绩单。 报告显示&#xff0c;公司一季度总营收866亿元&#xff0c;同比增长18%&#xff1b;核心本地商业收入643亿元&#xff0c;同比增长18%&#xff1b;季度研发投入58亿元&a…

【unity游戏开发——编辑器扩展】AssetPostprocessor和AssetImporter对导入的资源进行统一的预处理

注意&#xff1a;考虑到编辑器扩展的内容比较多&#xff0c;我将编辑器扩展的内容分开&#xff0c;并全部整合放在【unity游戏开发——编辑器扩展】专栏里&#xff0c;感兴趣的小伙伴可以前往逐一查看学习。 文章目录 前言一、AssetPostprocessor1、主要特点2、常用回调方法3、…

代码随想录算法训练营 Day61 图论ⅩⅠ Floyd A※ 最短路径算法

图论 题目 97. 小明逛公园 本题是经典的多源最短路问题。 在这之前我们讲解过&#xff0c;dijkstra朴素版、dijkstra堆优化、Bellman算法、Bellman队列优化&#xff08;SPFA&#xff09; 都是单源最短路&#xff0c;即只能有一个起点。 而本题是多源最短路&#xff0c;即求多…

CATIA高效工作指南——测量分析篇(一)

一、精准重心分析与实时更新技术 1.1 材料属性与几何体重心关联 在复杂零件设计中&#xff0c;重心控制直接影响产品性能。通过CATIA的材料属性系统可实现动态重心跟踪&#xff1a; ​​密度赋值​​&#xff1a;应用材料 → 选择单个几何体 /依次选择多个几何体→ 指定材质…

【PCB工艺】PCB设计中的基本概念

此文结合实例讲解PCB的设计流程和一些基本概念。 🧱 PCB 是什么? PCB(Printed Circuit Board)(即印制线路板) 是电子元器件的载体,是没有焊接任何器件的“裸板”。 PCB只是板子,没有焊接元件,而PCBA可以理解为焊接好元件的完成板子。 简单点说,PCB 只包含:铜线、电源…

深度学习|pytorch基本运算

【1】引言 pytorch是深度学习常用的包&#xff0c;顾名思义&#xff0c;就是python适用的torch包&#xff0c;在python里面使用时直接import torch就可以调用。 需要注意的是&#xff0c;pytorch包与电脑配置、python版本有很大关系&#xff0c;一定要仔细阅读安装要求、找到…

[Windows] 千库/六图素材下载工具

下载链接 夸克网盘分享&#xff08;点击蓝色自己自行保存下载&#xff09; 由吾爱大神分享一块下载工具 核心功能&#xff1a;无水印下载&#xff0c;圈网站素材覆盖&#xff0c;下载速度飞起&#xff0c;还能同时下载100个素材 使用方法&#xff1a; 双击运行 千库六图下…

SolidWorks 文件打开时电脑卡顿问题分析与解决

最近遇到一个问题就是我点击solid work的文件的时候会将电脑卡住然后电脑开始飞速的加载内存&#xff0c;鼠标移动很卡顿 解决办法&#xff1a; 1.找到资源管理器 当遇到这种情况时&#xff0c;可以尝试通过资源管理器来解决问题。首先&#xff0c;找到任务管理器&#xff08…

CppCon 2014 学习:Hourglass Interfaces for C++ APIs

共享库&#xff08;Shared Libraries&#xff09; 的基本结构和机制。 什么是 Shared Library&#xff1f; 共享库是在多个程序之间共享的一组可执行代码和数据&#xff0c;可以在运行时动态加载。 在 Windows 中通常是 .dll在 Linux 中是 .so&#xff08;Shared Object&…

<3>, 常用控件

目录 一、控件概述 二、QWidget 核心属性 1&#xff0c; 核心属性列表 2&#xff0c;enabled 3&#xff0c;geometry 4&#xff0c;windowTitle 5&#xff0c;windowIcon 6&#xff0c;windowOpacity 7&#xff0c;font 8&#xff0c;toolTip 9&#xff0c;focusPol…

基于微服务架构的社交学习平台WEB系统的设计与实现

设计&#xff08;论文&#xff09;题目 基于微服务架构的社交学习平台WEB系统的设计与实现 摘 要 社交学习平台 web 系统要为学习者打造一个开放、互动且社交性强的在线教育环境&#xff0c;打算采用微服务架构来设计并实现一个社交学习平台 web 系统&#xff0c;以此适应学…

uboot启动流程分析之uboot启动阶段

uboot启动可分为汇编语言执行和C语言执行两个阶段&#xff0c;两个阶段以_main函数为分界。 uboot第一阶段由_start (arch/arm/lib/vectors.S)进入&#xff0c;然后跳转到reset(arch/arm/cpu/armv7/start.S)函数, reset函数进行设置CPU运行模式&#xff0c;关闭中断等一系列CP…

QT学习教程(十一)

​​​​​​实现文件菜单&#xff08;Implementing the File Menu&#xff09; 我们实现与文件菜单有关的槽函数和相关的私有函数&#xff0c;以使文件菜单可以工作&#xff0c;同时管理最近打开文件列表。 void MainWindow::newFile(){if (okToContinue()) { spreadsheet-…

【MATLAB代码】制导方法——平行接近法引导,二维环境,动态目标|附代码的下载链接

平行接近法是一种导引方法&#xff0c;其目标是保持目标瞄准线在空间中的平行移动。 本文所述的代码实现了二维平行接近法导引的动态仿真&#xff0c;模拟导弹追踪移动目标的过程。通过实时调整导弹速度方向&#xff0c;确保其逐渐逼近目标&#xff0c;最终在设定距离内完成拦截…

解决win自动重启(自用,留链接)

2025-05-30修改&#xff0c;如果再出现重启回来修改。没动静就是没事了 1、依据系统事件查看器确认错误代码 事件查看器步骤 &#xff08;上图没啥用&#xff09; 下图错误代码&#xff0c;如果原因一致 2、禁用“用户体验改善计划”点击此处步骤

AI入门示例

市面上有很多AI大模型&#xff0c;这里以 智谱的大模型 为示例 1.先要注册智谱AI开放平台 2.注册成功后&#xff0c;会赠送3个月的免费额度&#xff0c;如下 3.然后去控制台&#xff0c;创建一个API KEY 4.接着就可以开始写代码了 提前导入包&#xff1a; openai 示例1&…

仿真每日一练 | 静力学分析与动力学分析的区别

很多有限元初学者都在纠结一个问题&#xff0c;就是静力学分析和动力学分析有什么区别&#xff0c;今天以一个时变载荷的例子&#xff0c;带大家领悟其中奥妙。 首先来了解一下二者的物理方程&#xff1a; 静力学所解决的问题&#xff1a;KxF 动力学所解决的问题&#xff1…