动态规划算法详解

article/2025/10/31 20:00:05

动态规划算法通常用于求解具有最优性质的问题

基本概念

      动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划(DP)。


基本思想与策略

      基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。

动态规划的算法设计

1:找出最优解的性质,并描述其结构特征

2:递归定义最优值

3:以自底向上的方式计算最优值

4:根据计算最优值时得到的信息构造出最优解

能采用动态规划求解的问题的一般要具有3个性质

      (1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
      (2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。

      (3) 有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)动态规划将原来具有指数级时间复杂度的搜索算法改进成了具有多项式时间复杂度的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。

使用动态规划求解问题,最重要的就是确定动态规划三要素

(1)问题的阶段 

(2)每个阶段的状态

(3)从前一个阶段转化到后一个阶段之间的递推关系

      递推关系必须是从次小的问题开始到较大的问题之间的转化,从这个角度来说,动态规划往往可以用递归程序来实现,不过因为递推可以充分利用前面保存的子问题的解来减少重复计算,所以对于大规模问题来说,有递归不可比拟的优势,这也是动态规划算法的核心之处。确定了动态规划的这三要素,整个求解过程就可以用一个最优决策表来描述,最优决策表是一个二维表,其中行表示决策的阶段,列表示问题状态,表格需要填写的数据一般对应此问题的在某个阶段某个状态下的最优值(如最短路径,最长公共子序列,最大价值等),填表的过程就是根据递推关系,从1行1列开始,以行或者列优先的顺序,依次填写表格,最后根据整个表格的数据通过简单的取舍或者运算求得问题的最优解:f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}
动态规划的具体步骤

      (1)划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。
      (2)确定状态和状态变量:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
      (3)确定决策并写出状态转移方程:因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。
      (4)寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。

求a到e最短路径。

举个例子:

问题 A: 【一本通基础DP背包】【例9.11】01背包问题

[题目描述]

一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是W_1,W_2,...,W_n,它们的价值分别为C_1,C_2,...,C_n,求旅行者能获得最大总价值。

输入

第一行:两个整数,N(物品数量n<=100)和M(背包容量,M<=10000);

第2..N+1行:每行二个整数W_i,C_i,表示每个物品的重量和价值。

输出

仅一行,一个数,表示最大总价值。

样例输入

4 10
2 1
3 3
4 5
7 9

样例输出

12
这道题就是用dp。状态转移方程式是:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - c[i]] + w[i]);

整个代码是

#include "bits/stdc++.h"
using namespace std;
int dp[120][10001], c[110], w[110], n, v;
int main()
{cin >> n >> v;for(int i = 1; i <= n; i++){cin >> c[i] >> w[i];}for(int i = 1; i <= n; i++){for(int j = 1; j <= v; j++){if(j < c[i])dp[i][j] = dp[i - 1][j];else{dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - c[i]] + w[i]);}}}cout << dp[n][v] << endl;return 0;
}

再附一道题

问题 J: 【一本通基础DP背包】宠物小精灵之收服

[题目描述]

宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事。

一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵。小智也想收服其中的一些小精灵。然而,野生的小精灵并不那么容易被收服。对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,野生小精灵也会对皮卡丘造成一定的伤害(从而减少皮卡丘的体力)。当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也不会被小智收服。当小智的精灵球用完时,狩猎也宣告结束。

我们假设小智遇到野生小精灵时有两个选择:收服它,或者离开它。如果小智选择了收服,那么一定会扔出能够收服该小精灵的精灵球,而皮卡丘也一定会受到相应的伤害;如果选择离开它,那么小智不会损失精灵球,皮卡丘也不会损失体力。

小智的目标有两个:主要目标是收服尽可能多的野生小精灵;如果可以收服的小精灵数量一样,小智希望皮卡丘受到的伤害越小(剩余体力越大),因为他们还要继续冒险。

现在已知小智的精灵球数量和皮卡丘的初始体力,已知每一个小精灵需要的用于收服的精灵球数目和它在被收服过程中会对皮卡丘造成的伤害数目。请问,小智该如何选择收服哪些小精灵以达到他的目标呢?

输入

输入数据的第一行包含三个整数:N(0<N<1000),M(0<M<500),K(0<K<100),分别代表小智的精灵球数量、皮卡丘初始的体力值、野生小精灵的数量。

之后的K行,每一行代表一个野生小精灵,包括两个整数:收服该小精灵需要的精灵球的数量,以及收服过程中对皮卡丘造成的伤害。

输出

输出为一行,包含两个整数:C,R,分别表示最多收服C个小精灵,以及收服C个小精灵时皮卡丘的剩余体力值最多为R。

样例输入

10 100 5
7 10
2 40
2 50
1 20
4 20

样例输出

3 30

附上代码

#include <bits/stdc++.h>
using namespace std;long long dp[1000][1000];
int n, m, k;
//n代表小智的精灵球数量, m代表皮卡丘初始的体力值
//k代表野生小精灵的数量
int c[1000];
int w[1000];
//c[i]表示最多收服C个小精灵
//w[i]表示以及收服C个小精灵时皮卡丘的剩余体力值最多为w
int main()
{scanf("%d%d%d", &n, &m, &k);for(int i = 1; i <= k; i++){scanf("%d%d", &c[i], &w[i]);}for(int i = 1; i <= k; i++){for(int j = n; j >= c[i]; j--){for(int l = m; l >= w[i]; l--){dp[j][l] = max(dp[j][l], dp[j - c[i]][l - w[i]] + 1);}}}printf("%d ", dp[n][m]);for(int i = 1; i <= m; i++){if(dp[n][i] == dp[n][m]){printf("%d", m - i);break;}}return 0;
}

http://chatgpt.dhexx.cn/article/SfXEd0G2.shtml

相关文章

动态规划原理

1. 基本概念 动态规划通过拆分问题&#xff0c;将问题拆分成许多的子问题&#xff0c;定义问题状态和状态之间的关系&#xff08;即状态转移方程或递推公式&#xff09;&#xff0c;使得问题能够以递推&#xff08;或者说分治&#xff09;的方式去解决。按顺序求解子问题&…

动态代理详解

想要更加透彻的理解动态代理&#xff0c;首先要熟悉下静态代理 一、静态代理 总结来说&#xff1a;目标类和代理类实现了相同的接口&#xff0c;在代理类中依赖了目标类&#xff0c;代理类的方法中调用了目标类的方法&#xff0c;并做了一些增强性的工作。 1、实现静态代理&…

CAD动态块制作

CAD动态块制作 拉伸动态块柜体A拉伸动态块制作第一步&#xff1a;制作柜体A第二步&#xff1a;进入块编辑器编辑第三步&#xff1a;关闭块编辑器 柜体B拉伸动态块制作第一步&#xff1a;制作柜体B第二步&#xff1a;进入块编辑器第三步&#xff1a;关闭块编辑器 可见性动态块第…

数据有效性 动态选择

EXCEL有两列数据栏&#xff0c;A列和B列&#xff0c;都是通过下来框来选择&#xff0c;要求A列选择完成后&#xff0c;B列动态调整可选择的内容。例如&#xff1a;第一例选择“AA”&#xff0c;第二列可供选择的范围是“a-d”&#xff1b;第一例选择“BB”&#xff0c;第二列可…

OTP 动态口令验证

OTP 动态口令验证。 简介 动态口令&#xff08;OTP&#xff0c;One-Time Password&#xff09;又称一次性密码&#xff0c;是使用密码技术实现的在客户端和服务器之间通过共享秘密的一种认证技术&#xff0c;是一种强认证技术&#xff0c;是增强目前静态口令认证的一种非常方…

loj#122.「强制在线」动态图连通性

loj#122. 「强制在线」动态图连通性 UPD:(7个月以后)这代码被叉了,我不想改了( negii真dl 然后发现这格式一更新…啊我的公式和链接怎么假掉了( csdn[] 算了不管了…反正这样子的话之后也不会用了( 题意 N 个点,M 次操作,支持加边/删边/询问两点间连通性。 强制在线。…

ORL、Yale等人脸数据库百度云链接

近段时间做人脸识别的实验&#xff0c;收集了几个人脸库&#xff0c;如图 这里放出百度云的链接&#xff0c;需要的自取 链接&#xff1a;https://pan.baidu.com/s/11_7bFdo_hhc83WQXmWtxvw 提取码&#xff1a;5ohd 强推这个文章&#xff0c;里面有16个人脸库的百度云链接 ht…

ORTP

1.为什么要使用RTP 一提到流媒体传输、一谈到什么视频监控、视频会议、语音电话&#xff08;VOIP&#xff09;&#xff0c;都离不开RTP协议的应用&#xff0c;但当大家都根据经验或者别人的应用而选择RTP协议的时候&#xff0c;你可曾想过&#xff0c;为什么我们要使用RTP来进行…

oracle中or的使用,Oracle Or

oracle函数 的 Oracle Or 在本教程中,我们来学习如何使用Oracle OR运算符来组合两个或更多的布尔表达式。 Oracle OR运算符介绍 OR运算符是一个逻辑运算符,它组合了布尔表达式,如果其中一个表达式为真(true),则返回true。 以下说明OR运算符的语法: expression_1 AND expre…

基于PCA方法的ORL人脸识别及Python代码实现

基于PCA方法的ORL人脸识别及Python代码实现 PCA算法方案设计代码实现结果分析参考文献 PCA的理论知识已经有很多博客做了清晰的解释&#xff0c;主要概括为找到投影的面使得类间误差最大&#xff0c;转化为找到构建的协方差的特征值与特征向量&#xff0c;在新的投影方向&#…

ORL Character Recgnition

文章目录 ORL Character Recgnition0 Abstract1 Introduction2 Related Work2.1 Character recognition2.2 Text detection 3 Connection Text Proposal Network3.1 Anchor3.2 Bi-Directional LSTM3.3 RPN layer3.4 Text line constructor3.5 Loss function3.6 Total system3.7…

ORL Faces Database介绍

ORL人脸数据集共包含40个不同人的400张图像&#xff0c;是在1992年4月至1994年4月期间由英国剑桥的Olivetti研究实验室创建。 此数据集下包含40个目录&#xff0c;每个目录下有10张图像&#xff0c;每个目录表示一个不同的人。所有的图像是以PGM格式存储&#xff0c;灰度图&…

基于ORL人脸数据库和PCA特征降维算法的人脸识别matlab仿真

目录 1.算法仿真效果 2.MATLAB核心程序 3.算法涉及理论知识概要 4.完整MATLAB 1.算法仿真效果 matlab2022a仿真结果如下&#xff1a; 2.MATLAB核心程序 ...................................................................... for i1:40sub_dir strcat(s, num2str(i))…

【图像处理matlab】PCA+KNN人脸识别 ORL人脸数据集

文章目录 0.写在前面1. 数据集导入与划分2. train-PCA构建脸空间2.1 原始数据导入2.2 去中心化2.3 求解协方差矩阵、特征值、特征向量2.4 特征脸选取--脸空间 3. test-物以类聚 KNN分类3.1 KNN简介3.2 KNN实现步骤3.2.1 距离度量---欧式距离、豪斯多夫距离.......3.2.2 k值选择…

Orcal 数据库

目录 一、数据库 1. 数据库概念 2. SQL 语言 3. Oracle结构 4. 表&#xff08;Table&#xff09; 5. 三范式 6. SELECT 语句 二、Orcal 基本操作 1. 查询列&#xff08;字段&#xff09; 2. 查询行&#xff08;记录&#xff09; 2.1 比较条件 2.2 且或非 2.3 null…

【人脸识别】基于PCA实现ORL人脸识别附matlab代码和报告

1 简介 人脸识别技术先进,应用广泛。借助PCA算法,利用MATLAB GUI可以简单操作,通过对待识别图像的预处理即可提高识别率。本文首先对相关概念进行了阐述,对工作原理进行了介绍,具体对基于PCA算法人脸识别的MATLAB实现进行了解析。 2 部分代码 function [neednum,average_face…

orical

truncate 和delete table 表名&#xff08;前面效率比后面高&#xff0c;而且前面执行后无法停止&#xff0c;前面会将orical查找数据时使用的节点删除&#xff0c;后面不会&#xff09; select * from 表名 会消耗大量资源不建议使用了&#xff1b; creat table 表名 as selec…

基于BP神经网络和ORL库的人脸识别matlab仿真

目录 一、理论基础 二、案例背景 1.问题描述 2.思路流程 三、部分MATLAB代码 四、仿真结论分析 五、参考文献 一、理论基础 这里&#xff0c;人脸的识别主要依据如下的流程进行&#xff1a; 具体的算法流程是这么一个过程&#xff1a; 第一&#xff1a;首先初始化一个区…

图像处理ORL--训练集及测试集建立--Matlab实现

在深度学习的研究与学习过程中&#xff0c;往往对神经网络的网络结构以及代码有比较好的理解&#xff0c;但基于matlab的数据集建立等操作经常困扰初学者。 今天带来matlab数据集建立的文件结构与代码。 文件格式 首先将图片保存在当前运行文件的文件夹中&#xff0c;将其命名…

深度学习入门_对ORL数据集进行特征提取降维后SVM分类

ORL人脸数据集共包含40个不同人的400张图像。所有图像都是以PGM格式存储的灰度图。每一个目录下的图像是在不同的时间、不同的光照、不同的面部表情条件下采集的。在该数据集中&#xff0c;每个人有10张照片。这10张照片中&#xff0c;前8张作为训练集&#xff0c;而后2张归为测…