C++-----动态规划

news2024/11/18 9:49:29

目录

一、动态规划的基本思想

 二、设计动态规划法的步骤

三、动态规划问题的特征

4.1 矩阵连乘积问题

 4.1.1 分析最优解的结构

4.1.2 建立递归关系

4.1.3 计算最优值

 4.1.3 计算最优值

 4.1.3 构造最优解

 4.2 动态规划算法的基本要素

4.2.1 最优子结构

4.2.2 重叠子问题

 算法4.3  计算矩阵连乘积的递归算法

4.1.3 备忘录方法

算法4.4计算矩阵连乘积的备忘录算法

 ​编辑

 4.3 最长公共子序列

 4.3.2 子问题的递归结构

 4.3.3 计算最优值

 4.4 最大子段和


一、动态规划的基本思想

  • 动态规划算法通常用于求解具有某种最优性质的问题。
  • 在这类问题中,可能会有许多可行解。
l 每一个解都对应于一个值,我们希望找到具有最优值的解。
  • 基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
l 适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。
  • 如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。
l 我们 可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。
  • 就是动态规划法的基本思路。
l 具体的动态规划算法多种多样,但它们具有相同的填表格式。

 二、设计动态规划法的步骤

1. 找出最优解的性质,并刻画其结构特征;
2. 递归地定义最优值(写出动态规划方程);
3. 以自底向上的方式计算出最优值;
4. 根据计算最优值时得到的信息,构造一个最优解。
l 步骤 1 3 是动态规划算法的基本步骤。
l 只需要求出最优值的情形,步骤 4 可以省略;
l 需要求出问题的一个最优解,则必须执行步骤 4。

三、动态规划问题的特征

  • 动态规划算法的有效性依赖于问题本身所具有的两个重要性质:
1. 优子结构:
  • 当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。
2. 重叠 子问题:
  • 在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。

4.1 矩阵连乘积问题

  • m×n矩阵An×p矩阵B相乘需耗费 的时间
  • 我们mnp作为两个矩阵相乘所需时间的测量值
  • 现在假定要计算三个矩阵ABC的乘积,有两种方式计算此乘积
1. A 乘以 B 得到矩阵 D ,然后 D 乘以 C 得到最终结果,这种乘法的 顺序为 AB C
2. 乘法的顺序为 A BC
  • 尽管这两种不同的计算顺序所得的结果相同,但时间消耗会有很大的差距。

 

 

  • 定义:给定n个矩阵{A1,A2,…,An},其中AiAi+1是可乘的,i=1,2,…n-1。考察这n个矩阵的连乘积A1A2…An。
  • 由于矩阵乘法满足结合律,所以计算矩阵的连乘可以有许多不同的计算次序。
  • 这种计算次序可以用加括号的方式来确定。
  • 若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积

  • 完全加括号的矩阵连乘积可递归地定义为:
1. 单个矩阵是完全加括号的;
2. 矩阵连乘积 A 是完全加括号的,则 A 可表示为 2 个完全加括号的矩阵连乘积 B C 的乘积并加括号,即A=(BC)   
  • 设有四个矩阵A, B, C, D,总共有五种完全加括号的方式:

(A((BC)D))

(A(B(CD)))

((AB)(CD))

(((AB)C)D)

((A(BC)D))

  • 设有四个矩阵A, B, C, D,它们的维数分别是:

  A=50×10,  B=10×40,  C=40×30,  D=30×5

  • 矩阵AB可乘的条件: 矩阵A的列数等于矩阵B的行数。
  • Ap×q的矩阵, Bq×r的矩阵, 乘积是p×r的矩阵;
计算量是 pqr。
  • 上述5种完全加括号方式的计算工作量为:

(A((BC)D)), (A(B(CD))), ((AB)(CD)), (((AB)C)D), ((A(BC)D))

      16000,    10500,   36000,       87500,         34500

BC: 10×40×30 = 12000,

(BC)D: 10×30×5 = 1500,

(A((BC)D)): 50×10×5 = 2500

 

  • 给定n个矩阵{A1,A2,…,An},其中AiAi+1是可乘的,i=12…n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少?
  • 穷举法:列举出所有可能的计算次序,并计算出每一种计算次序相应需要的数乘次数,从中找出一种数乘次数最少的计算次序。

 

 4.1.1 分析最优解的结构

  • 将矩阵连乘积AiAi+1Aj 简记为A[i:j], 这里ij;
  • 考察计算A[1:n]的最优计算次序。
  • 设这个计算次序在矩阵AkAk+1之间将矩阵链断开,1k<n,则其相应完全加括号方式为(A1A2…Ak)(Ak+1Ak+2…An)
  • 计算量:A[1:k]的计算量加上A[k+1:n]的计算量,
  • 再加上A[1:k]A[k+1:n]相乘的计算量
  • 特征:计算A[1:n]的最优次序所包含的计算矩阵子链 A[1:k]A[k+1:n]的次序也是最优的。
  • 矩阵连乘计算次序问题的最优解包含着其子问题的最优解。
  • 这种性质称为最优子结构性质
  • 问题的最优子结构性质是该问题可用动态规划算法求解的显著特征。

4.1.2 建立递归关系

 

 

4.1.3 计算最优值

  • 对于1ijn不同的有序对(i, j)对应于不同的子问题。因此,不同子问题的个数最多只有
  • 在递归计算时,许多子问题被重复计算多次。
  • 这也是该问题可用动态规划算法求解的又一显著特征。
  • 用动态规划算法解此问题,可依据其递归式以自底向上的方式进行计算。
  • 在计算过程中,保存已解决的子问题答案。
  • 每个子问题只计算一次,在后面需要时只要简单查一下,从而避免大量的重复计算,最终得到多项式时间的算法。

 

#define NUM 51
int p[NUM];
int m[NUM][NUM];
int s[NUM][NUM];
void MatrixChain (int n)
{
  for (int i=1;  i<=n;  i++) m[i][i] = 0;
  for (int r=2;  r<=n;  r++)
	for (int i=1;  i<=n-r+1;  i++) 
	{
	  int j=i+r-1; 
	  //计算初值,从i处断开
	  m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
	  s[i][j] = i; 
	  for (int k=i+1;  k<j;  k++) 
	  { 
		int t = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
		if (t < m[i][j]) {m[i][j] = t; s[i][j] = k;}
	  }
	}
}

 

 4.1.3 计算最优值

                                                                                                    计算顺序

 

 

 

 

  • 依据其递归式以自底向上的方式进行计算。
  • 在计算过程中 , 保存已解决的子问题答案。
  • 每个子问题只计算一次 , 而在后面需要时只要简单查一下 ,从而避免大量的重复计算, 最终得到多项式时间的算法。

 

         计算顺序

 4.1.3 构造最优解

  • s[i][j]已经存储了构造最优解所需要的足够的信息。
  • 每个部分的最优加括号方式可以根据数组s的相应元素得出。
  • 照此递推下去,最终可以确定A[1:n]的最优完全加括号方式,即构造出问题的一个最优解。
//算法4.2计算矩阵连乘积最优解的递归算法
void TraceBack(int i, int j) 
{ 
	if(i==j) printf("A%d", i);
	else 
	{
		printf("(");
		TraceBack(i,s[i][j]); 
		TraceBack(s[i][j]+1,j); 
		printf(")"); 
	}
}

 

 4.2 动态规划算法的基本要素

4.2.1 最优子结构

  • 设计动态规划算法的第一步是刻画最优解的结构。
  • 当问题的最优解包含其子问题的最优解时,称该问题具有最优子结构性质。
  • 问题的最优解子结构性质提供了该问题可用动态规划求解的重要线索。
  • 动态规划算法中,利用问题的最优子结构性质,以自底向上的方法递归的从子问题的最优解逐步构造出整个问题的最优解
  • 使我们能在相对小的子问题空间中考虑问题。

4.2.2 重叠子问题

  • 递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。
  • 这种性质称为子问题的重叠性质。
  • 动态规划算法,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只是简单地用常数时间查看一下结果。

  • 通常不同的子问题个数随问题的大小呈多项式增长。
  • 用动态规划算法只需要多项式时间,从而获得较高的解题效率。

 

 算法4.3  计算矩阵连乘积的递归算法

//算法4.3  计算矩阵连乘积的递归算法

int Recurve(int i, int j)
{
  if (i == j) return 0;
  int u = Recurve(i, i)+Recurve(i+1,j)+p[i-1]*p[i]*p[j];
  s[i][j] = i;
  for (int k = i+1; k<j; k++) 
  {
	int t = Recurve(i, k) + Recurve(k+1,j)+p[i-1]*p[k]*p[j];
	if (t<u) { u = t; s[i][j] = k;}
  }
  m[i][j] = u;
  return u;
} 

 

 

 

 

4.1.3 备忘录方法

  • 备忘录方法是动态规划算法的变形。
  • 与动态规划算法一样,备忘录方法用一个表格保存已解决的子问题的答案,再碰到该子问题时,只要简单地查看该子问题的解答,而不必重新求解。
  • 备忘录方法的控制结构与直接递归方法的控制结构相同,区别仅在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。

算法4.4计算矩阵连乘积的备忘录算法

int LookupChai  (int i, int j)
{
  if (m[i][j]>0) return m[i][j];
  if (i==j) return 0;
  int u = LookupChain(i,i)+LookupChain(i+1,j)+p[i-1]*p[i]*p[j];
  s[i][j] = i;
  for (int k = i+1; k<j; k++) 
  {
	int t = LookupChain(i,k)+LookupChain(k+1,j)+p[i-1]*p[k]*p[j];
	if (t < u) { u = t; s[i][j] = k;}
  }
  m[i][j] = u;
  return u;
}

 

 4.3 最长公共子序列

  • 若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij
  • 例如,序列Z={BCDB}是序列X={ABCBDAB}的子序列,相应的递增下标序列为{2357}
  • 给定2个序列XY,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列XY公共子序列
  • 给定2个序列X={x1,x2,…,xm}Y={y1,y2,…,yn},找出XY的最长公共子序列。

  • 设序列X={x1,x2,…,xm}Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk} ,则
  1. xm=yn,则zk=xm=yn,且zk-1xm-1yn-1的最长公共子序列。
  2. xm≠ynzk≠xm,则Zxm-1Y的最长公共子序列。
  3. xm≠ynzk≠yn,则ZXyn-1的最长公共子序列。

 

 4.3.2 子问题的递归结构

  • 由最长公共子序列问题的最优子结构性质可知,要找出XY的最长公共子序列,可按以下方式递归地进行:
  1. xmyn时,找出Xm1Yn1最长公共子序列,然后在其尾部加上xm(=yn)即可得XY的一个最长公共子序列。
  2. xmyn时,必须解两个子问题,即找出Xm1Y的一个最长公共子序列及XYn1一个最长公共子序列。这两个公共子序列中较长者为XY的一个最长公共子序列。

  • c[i][j]记录序列和的最长公共子序列的长度。
  • Xi={x1,x2,…,xi}Yj={y1,y2,…,yj}
  • i=0j=0时,空序列是XiYj的最长公共子序列。
  • 故此时C[i][j]=0
  • 其它情况下,由最优子结构性质可建立递归关系如下:

 4.3.3 计算最优值

//算法4.5计算最长公共子序列的动态规划算法
#define NUM 100
int c[NUM][NUM];
int b[NUM][NUM];
void LCSLength (int m, int n, const char x[],char y[])
{  
  int i,j;
  //数组c的第0行、第0列置0
  for (i = 1; i <= m; i++) c[i][0] = 0;
  for (i = 1; i <= n; i++) c[0][i] = 0;
  //根据递推公式构造数组c
  for (i = 1; i <= m; i++)
  for (j = 1; j <= n; j++)
  {
	if (x[i]==y[j]) 
	  {c[i][j]=c[i-1][j-1]+1; b[i][j]=1; }		//↖
	else if (c[i-1][j]>=c[i][j-1]) 
		{c[i][j]=c[i-1][j]; b[i][j]=2; }		//↑
	else { c[i][j]=c[i][j-1]; b[i][j]=3; }			//←
  }
}

 

 

 

 4.4 最大子段和

  • 给定由n个整数(包含负整数)组成的序列a1,a2,...,an,求该序列子段和的最大值。
  • 当所有整数均为负值时定义其最大子段和为0
  • 所求的最优值为:

  • 例如,当(a1,a2, ……a7,a8)=(1,-3, 7,8,-4,12, -10,6)时,最大子段和为:

                                   

  •  bj1j位置的最大子段和:

 

 

 

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

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

相关文章

gRPC结合vcpkg在x64-windows平台visual studio2019 cmake工程里面的应用

这里我们运用vcpkg去下载安装gRPC&#xff0c;进入vcpkg目录后&#xff0c;执行命令&#xff1a;.\vcpkg.exe install grpc:x64-windows grpc在vcpkg里面安装完成后&#xff0c;我们就来使用grpc做一个简单的例子。 gRPC顾名思义&#xff0c;就是google的RPC方案&#xff0c;…

ProtoBuf 编码原理

因为涉及到分布式集群之间的通信&#xff0c;所以来学习了下 ProtoBuf&#xff0c;为什么选择 ProtoBuf 呢&#xff1f;主要还是因为相对于 json , xml 来说&#xff0c;ProtoBuf 传输效率更快&#xff0c;故需要了解下它的编码设计。 首先&#xff0c;每一个 message 进行编码…

科研人必看入门攻略(收藏版)

来源&#xff1a;投稿 作者&#xff1a;小灰灰 编辑&#xff1a;学姐 本文主要以如何做科研&#xff0c;日常内功修炼&#xff0c;常见科研误区&#xff0c;整理日常‘好论文’四个部分做以介绍&#xff0c;方便刚入门的科研者进行很好的规划。 1.如何做科研 1.1 选方向 当我…

【2023年第十一届泰迪杯数据挖掘挑战赛】A题:新冠疫情防控数据的分析 32页和40页论文及实现代码

【2023年第十一届泰迪杯数据挖掘挑战赛】A题&#xff1a;新冠疫情防控数据的分析 32页和40页论文及实现代码 相关链接 &#xff08;1&#xff09;建模方案 【2023年第十一届泰迪杯数据挖掘挑战赛】A题&#xff1a;新冠疫情防控数据的分析 建模方案及python代码详解 &#x…

【初学人工智能原理】【4】梯度下降和反向传播:能改(下)

前言 本文教程均来自b站【小白也能听懂的人工智能原理】&#xff0c;感兴趣的可自行到b站观看。 本文【原文】章节来自课程的对白&#xff0c;由于缺少图片可能无法理解&#xff0c;故放到了最后&#xff0c;建议直接看代码&#xff08;代码放到了前面&#xff09;。 代码实…

《LearnUE——基础指南:开篇—2》——准备工作

目录 0.2.1 UE的获取与创建项目 0.2.2 UE4编辑器界面布局 1. 编辑器介绍 2. 新建蓝图与蓝图拖动 3. 菜单介绍 4. 工具栏介绍 0.2.3 学习资料 0.2.1 UE的获取与创建项目 登录UE官网&#xff1a;www.unrealengine.com 点击“登录”&#xff0c;如果没有账号&#xff0…

自动驾驶——离散系统LQR的黎卡提方程Riccati公式推导与LQR工程化

1.LQR Question Background 之前写过连续系统的黎卡提方程Riccati推导,但是考虑到实际工程落地使用的是离散系统,于是又进行了离散黎卡提方程Riccati的公式推导。 2.Proof of Riccati Equation Formula for Discrete Systems 工程化落地,就是使用公式(2-14)实时计算控制率…

Windows编译安装AzerothCore魔兽世界开源服务端Lua脚本引擎Eluna和防作弊anticheat模块教程

Windows编译安装AzerothCore魔兽世界开源服务端Lua脚本引擎Eluna和防作弊anticheat模块教程 大家好&#xff0c;我是艾西今天和大家聊聊魔兽世界游戏内的脚步以及防作弊模块 Eluna是azerothcore服务端的Lua脚本引擎&#xff0c;可以在原有azerothcore的基础上实现很多拓展以及…

Linux操作系统指令(1)

目录 一、什么是Linux操作系统&#xff1f;二、Linux基本指令12.1 ls指令2.2 pwd指令2.3 cd指令2.4 touch指令2.5 mkdir指令&#xff08;非常重要&#xff09;2.6 rmdir指令 && rm 指令&#xff08;十分重要&#xff09;2.7 man指令&#xff08;非常重要&#xff09;2.…

基于松鼠算法的极限学习机(ELM)回归预测-附代码

基于松鼠算法的极限学习机(ELM)回归预测 文章目录 基于松鼠算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于松鼠算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用松鼠算法对极限学习机进行优化&#xff0c;并…

设计模式-创建型模式-(工厂、简单工厂、抽象工厂)

一、简单工厂模式 上代码 public class FoodFactory {public static Food makeFood(String name) {if (name.equals("noodle")) {Food noodle new LanZhouNoodle();noodle.addSpicy("more");return noodle;} else if (name.equals("chicken")…

Java中的注解和反射

注解 在Java程序中&#xff0c;我们可以在很多地方看到注解&#xff0c;如一下情况: 注解有检查和约束的作用 内置注解 当被Deprecated注解修饰的方法被使用的时候&#xff0c;方法会被画上杠&#xff1a; 元注解 当我们打开一个注解的时候&#xff0c;可以看到以下这些信…

一份标准的软件测试方案模板

第一章 概述 ​ 软件的错误是不可避免的&#xff0c;所以必须经过严格的测试。通过对本软件的测试&#xff0c;尽可能的发现软件中的错误&#xff0c;借以减少系统内部各模块的逻辑&#xff0c;功能上的缺陷和错误&#xff0c;保证每个单元能正确地实现其预期的功能。检测和排…

ROS 视觉建图不显示点云

I 乐视摄像头找不到彩色输出&#xff08;供参考&#xff09; 1.安装依赖 sudo apt install ros-$ROS_DISTRO-rgbd-launch ros-$ROS_DISTRO-libuvc ros-$ROS_DISTRO-libuvc-camera ros-$ROS_DISTRO-libuvc-ros2.进入ROS摄像机目录 cd /home/wheeltec/wheeltec_robot/src/ros_…

[计算机图形学]动画与模拟:关键帧动画、质点弹簧系统、运动学与绑定(前瞻预习/复习回顾)

一、动画的简要概念 动画和语言一样&#xff0c;一开始都是作为传达信息的工具。什么是动画呢&#xff1f;简单的理解就是让画面变成“活的”&#xff0c;也就是让它们能够动起来&#xff0c;其次需要一定的美观。在图形学上&#xff0c;我们可以把动画理解为建模或者是几何的一…

1.1 n阶行列式子的定义

学习目标&#xff1a; 掌握n阶行列式的定义和计算方法&#xff0c;并能够解决相关的数学问题。 学习步骤&#xff1a; 学习n阶行列式的定义&#xff0c;需要一定的抽象思维能力和数学基础。 了解基本概念和性质&#xff1a;在学习n阶行列式之前&#xff0c;需要先了解行列式…

设计模式——工厂模式(简单工厂、工厂方法、抽象工厂)

是什么&#xff1f; 工厂模式的目的是将创建对象的具体过程隐藏起来&#xff0c;从而达到更高的灵活性 工厂模式分为&#xff1a;简单工厂模式、工厂方法模式、抽象工厂模式&#xff1b; 为什么&#xff1f; 在Java中&#xff0c;万物皆是对象&#xff0c;我们在使用的时候…

(8) 支持向量机(下)(模型评估指标、ROC曲线)

文章目录 1 二分类SVC的进阶1.1 参数C的理解进阶1.2 二分类SVC中的样本不均衡问题&#xff1a;重要参数class_weight 2 SVC的模型评估指标2.1 混淆矩阵2.1.1 模型整体效果&#xff1a;准确率2.1.2 捕捉少数类的艺术&#xff1a;精确度&#xff0c;召回率和F1 score2.1.3 判错多…

【fluent】axial、radial、tangentia的含义和区别,axial/radial/tangentia coordination表达的意义

Reference 本文主要参考fluent的官方文档。 ANSYS FLUENT 12.0 User’s Guide - 31.2 Velocity Reporting Options 笛卡尔坐标系——Cartesian coordinate system 不管什么坐标系&#xff0c;都要讲究维数。这个维数根据问题难度确定&#xff0c;对于3D问题需要用三维坐…

魔兽服务端编译部署NPCBots和 Al机器人模块教程

魔兽服务端编译部署NPCBots和 Al机器人模块教程 大家好&#xff0c;我是艾西。在平时自己一个人玩魔兽的时候是不是会比较无聊&#xff0c;因为游戏机制或副本难度自己一个人无法进行快乐的玩耍。今天艾西教大家编译部署NPCBots和 Al机器人模块&#xff0c;直接一个人玩魔兽也…