南邮|算法分析与设计实验二 动态规划法

article/2025/9/29 20:39:08

目录

实验目的

实验内容

实验步骤

一、最长公共子序列

二、矩阵连乘 


实验目的

加深对动态规划法的算法原理及实现过程的理解,学习用动态规划法解决实际应用中的最长公共子序列问题矩阵连乘问题,体会动态规划法备忘录方法的异同。

实验内容

一、用动态规划法和备忘录方法实现求两序列的最长公共子序列问题。要求掌握动态规划法思想在实际中的应用,分析最长公共子序列的问题特征,选择算法策略并设计具体算法,编程实现两输入序列的比较,并输出它们的最长公共子序列。

二、用动态规划法和备忘录方法求解矩阵相乘问题,求得最优的计算次序以使得矩阵连乘总的数乘次数最少,并输出加括号的最优乘法算式。 

实验步骤

一、最长公共子序列

1、最长公共子序列(Longest Common Subsequence,LCS)问题是:给定两个字符序列\mathbf{\textbf{}X=\left \{ x_{1}, x_{2} ,......, x_{m}\right \}} 和\mathbf{\textbf{}Y=\left \{ y_{1}, y_{2} ,......, y_{m}\right \}} ,要求找出 A 和 B 的一个最长公共子序列。 例如:\mathbf{\textbf{}X=\left \{ a,b,c,b,d,a,b\right \}}\mathbf{\textbf{}Y=\left \{ b,d,c,a,b,a\right \}}。它们的最长公共子序列\mathbf{ LSC=\left \{ b,c,b,a \right \}}。 通过“穷举法”列出 X 的所有子序列,检查其是否为 Y 的子序列并记录最长公共子序列的 长度这种方法,求解时间为指数级的,因此不可取。

2、分析 LCS 问题特征可知,如果 \mathbf{\textbf{}Z=\left \{ z_{1},z_{2},......,z_{k} \right \}}为它们的最长公共子序列,则它们一定 具有以下性质:

        (1)若 \mathbf{x_{m}=y_{n}},则\mathbf{z_{k}=x_{m}=y_{n}} ,且 \mathbf{Z_{k-1}}\mathbf{X_{m-1}} 和 \mathbf{Y_{n-1}} 的最长公共子序列;

        (2)若 \mathbf{x_{m}\neq y_{n}}\mathbf{z_{k}\neq x_{m}},则 \boldsymbol{Z \mathbf{}}\mathbf{X_{m-1}}\textbf{Y\textbf{}} 的最长公共子序列;

        (3)若\mathbf{x_{m}\neq y_{n}}\mathbf{z_{k}\neq y_{n}},则  \boldsymbol{Z \mathbf{}}\mathbf{X}\mathbf{Y_{n-1}}的最长公共子序列。

        这样就将求\mathbf{X\mathbf{}}\mathbf{Y} 的最长公共子序列问题,分解为求解较小规模的子问题:

        \bigstar\mathbf{x_{m}=y_{n}},则进一步分解为求解两个(前缀)子字符序列 \mathbf{X_{m-1}}\mathbf{Y_{n-1}} 的最长公共子序列 问题;

        \bigstar 如果\mathbf{x_{m}\neq y_{n}},则原问题转化为求解两个子问题,即找出 \mathbf{X_{m-1}}\textbf{Y\textbf{}} 的最长公共子序列与 找出 \mathbf{X}\mathbf{Y_{n-1}} 的最长公共子序列,取两者中较长者作为 \mathbf{X\mathbf{}}\mathbf{Y} 的最长公共子序列。

         由此可见,两个序列的最长公共子序列包含了这两个序列的前缀的最长公共子序列,具有最优子结构性质。 

3、令c[i][j]保存字符序列\mathbf{\textbf{}X_{i}=\left \{ x_{1}, x_{2} ,......, x_{i}\right \}}\mathbf{\textbf{}X_{j}=\left \{ x_{1}, x_{2} ,......, x_{j}\right \}}的最长公共子序列的长度。 由上述分析可得如下递推式:

\mathbf{c[i][j]=\left\{\begin{matrix} 0 &i=0\, \, \, \, or\, \, \, \, j=0 \\ c[i-1][j-1]+1&i,j>0\, \, \, \, and\, \, \, \, x_{i}=y_{j} \\ max\left \{ c[i][j-1],c[i-1][j] \right \}& i,j>0\, \, \, \, and\, \, \, \, x_{i}\neq y_{j} \end{matrix}\right.}

由此可见,最长公共子序列的求解具有重叠子问题性质,如果采用递归算法实现,会得到一个指数时间算法。因此需要采用动态规划法自底向上求解,并保存子问题的解,这样可以避免重复计算子问题,在多项式时间内完成计算。

4、为了能由最优解值进一步得到最优解(即最长公共子序列),还需要一个二维数组 s[][], 数组中的元素 s[i][j]记录 c[i][j]的值是由三个子问题 c[i-1][j-1]+1,c[i][j-1]和 c[i-1][j]中的哪一个计算得到,从而可以得到最优解的当前解分量(即最长公共子序列中的当前字符),最终构造出最长公共子序列自身。

5、计算最长公共子序列长度,并给出最长公共子序列:

(注意:C 语言中数组下标由 0 开始,而实际数据在一维数组 a、b 和二维数组 c、s 中的存放却是从下标为 1 处开始。)

二维数组 c 和 s 用于动态规划法求解过程中保存子问题的求解结果,一维数组 a 和 b 用于存放两个字符序列,m 和 n 为两个字符序列中实际字符的个数。

#include <iostream>
#include <cstring>
#define MAX 1024
using namespace std;int m,n;
string a,b;
int c[MAX][MAX],s[MAX][MAX];int LCSLength() {for(int i=1; i<=m; i++) {for(int j=1; j<=n; j++) {if(a[i]==b[j]) {c[i][j]=c[i-1][j-1]+1;s[i][j]=1;} else if(c[i][j-1]>c[i-1][j]) {c[i][j]=c[i][j-1];s[i][j]=2;} else {c[i][j]=c[i-1][j];s[i][j]=3;}}}return c[m][n];
}void CLCS(int i,int j) {if(s[i][j]==0)  return;if(s[i][j]==1) {CLCS(i-1,j-1);cout << a[i];} else if(s[i][j]==2) {CLCS(i,j-1);} else if(s[i][j]==3) {CLCS(i-1,j);}
}int main() {cin >> a >> b;m = a.length();n = b.length();a = '0'+a;b = '0'+b;for(int i=0; i<=m; i++)for(int j=0; j<=n; j++)c[i][j]=0,s[i][j]=0;cout << "最长公共子序列长度是:" << LCSLength() << endl;		cout << "最长公共子序列为:";CLCS(m,n);return 0;
}

7、输入序列 \mathbf{\textbf{}X=\left \{ x_{1}, x_{2} ,......, x_{m}\right \}=\left \{ a,b,c,b,d,a,b \right \}}\mathbf{\textbf{}Y=\left \{ y_{1}, y_{2} ,......, y_{n}\right \}=\left \{ b,d,c,a,b,a \right \}}作为测试数据, 测试程序是否能够正确运行?输出结果是什么?

 8、分析该动态规划算法的两个主要成员函数 int LCSLength()和 void CLCS()的时间复杂性。

O\left ( m\times n \right ),O(m+n)

二、矩阵连乘 

1、求解目标 若 n 个矩阵\left \{ A_{1} ,A_{2},.....A_{n}\right \}中两个相邻矩阵 A_{i}A_{i+1均是可乘的,A_{i}的维数为 p_{i}p_{i+1}A_{i+1} 的维数为 p_{i+1} p_{i+2}。求 n 个矩阵\left \{ A_{1} ,A_{2},.....A_{n}\right \} 连乘时的最优计算次序,以及对应的最少 数乘次数。 两矩阵相乘 A_{i}A_{i+1}p_{i}p_{i+1}p_{i+2}次数乘,可得 p_{i}p_{i+2}的结果矩阵。而矩阵连乘 \left \{ A_{i} ,A_{i+1},.....A_{j}\right \}(简记为 A[i:j])求得 p_{i}p_{i+1} 的结果矩阵时,采用不同的计算次序,对应的总数乘次数也不同。

2、例如:4 个矩阵连乘 A_{1}A_{2}A_{3}A_{4},其中A_{1}的维数:50×10,A_{2}的维数:10×40,A_{3} 的维数: 40×30,A_{4}的维数:30×5。有 5 种不同的计算次序:

次序 1:\left ( \left ( \left ( A_{1} A_{2} \right ) A_{3} \right ) A_{4} \right )     需要 50×10×40+50×40×30+50×30×5=87500 次

次序 2:((A_{1} A_{2}) (A_{3} A_{4} ))      需要 50×10×40+40×30×5+50×40×5=36000 次

次序 3:((A_{1} (A_{2} A_{3}) )A_{4} )      需要 10×40×30+50×10×30+50×30×5=34500 次

次序 4:(A_{1}((A_{2} A_{3}) A_{4} ))      需要 10×40×30+10×30×5+50×10×5=16000 次

次序 5:( A_{1} (A_{2}( A_{3} A_{4} )))      需要 40×30×5+10×40×5+50×10×5=10500 次

3、将二维数组 m[i][j]定义为:计算 A[i:j]所需的最少数乘次数;

二维数组 s[i][j]定义为:计算 A[i:j]的最优计算次序中的断开位置(例如:若计算 A[i: j]的最优次序在A_{k}A_{k+1}之间断开,i≤k<j,则 s[i][j]=k)。

 4、当 i=j 时,A[i:j]=Ai是单一矩阵,无须计算,因此 m[i][j]=0;

      当 i<j 时m[i][j]=min\left \{ m[i][k]+m[k+1][j]+p_{i}p_{k+1}p_{j+1} \right \} (i\leqslant k<j)

5、算法思路

因为计算 m[i][j]时,只用到已计算出的 m[i][k]和 m[k+1][j]。所以首先计算出 m[i][i]=0, i=1,2,……n;然后再根据递归式,按矩阵链长递增的方式依次计算 m[i][i+1],i=1,2,…n-1(矩阵链长度为 2);m[i][i+2],i=1,2,…n-2(矩阵链长度为 3);……则 m[1][n]就是问题 的最优解值(最少数乘次数)。

要构造问题的最优解,根据 s 数组可推得矩阵乘法的次序。从 s[1][n]可知计算 A[1:n] 的最优加括号方式为(A[1:s[1][n]])(A[s[1][n]+1:n])。其中 A[1:s[1][n]]的最优加括号方式 又为(A[1:s[1][s[1][n]]])(A[s[1][s[1][n]]+1:s[1][n]])。……照此递推下去,最终可以确定 A[1:n]的最优完全加括号方式,构造出问题的一个最优解。 

6、动态规划法实现的算法提示 (请分别对实例 1:A_{1} 维数:50×10,A_{2} 维数:10×40,A_{3} 维数:40×30,A_{4} 维数: 30×5 和实例 2:A_{1} 维数:30×35,A_{2} 维数:35×15,A_{3}维数:15×5,A_{4}维数:5×10;A_{5}维数:10×20,A_{6} 维数:20×25 分别求解。)

#include <iostream>
#include <cstring>
#define MAX 1024
using namespace std;int n;
int p[MAX];
int m[MAX][MAX],s[MAX][MAX];int MChain() {for(int r=1; r<n; r++) {for(int i=0; i<n-r; i++) {int j = i+r;m[i][j]=m[i][i]+m[i+1][j]+p[i]*p[i+1]*p[j+1];s[i][j]=i;for(int k=i+1; k<j; k++) {int t = m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];if(t<m[i][j]) {m[i][j]=t;cout<<"更新m["<<i<<"]["<<j<<"]的值为:"<<t<<endl;s[i][j]=k;cout<<"更新s["<<i<<"]["<<j<<"]的值为:"<<k<<endl;}}cout<<"最终求出:m["<<i<<"]["<<j<<"]的值为:"<<m[i][j]<<endl;}}return m[0][n-1];
}void Traceback(int i,int j) {if(i==j) {cout << 'A' << i;return ;}if(i<s[i][j]) cout << '(';Traceback(i,s[i][j]);if(i<s[i][j]) cout << ')';if(s[i][j]+1<j) cout << '(';Traceback(s[i][j]+1,j);if(s[i][j]+1<j) cout << ')';
}int main() {cin >> n;for(int i=0; i<=n; i++) {cin>>p[i];}for(int i=0; i<n; i++) {m[i][i] = 0;s[i][i]=i;}cout << "最少数乘次数:" <<  MChain() << endl;cout << "最优计算次序:" << '(';Traceback(0,n-1);cout << ')';return 0;
}


http://chatgpt.dhexx.cn/article/57o1dP3H.shtml

相关文章

动态规划--算法

1、动态规划&#xff1a;将求解问题分解成若干个子问题&#xff0c;求解子问题&#xff0c;这些子问题不是独立的 求解后的子问题都会记录到表中&#xff0c;每个子问题仅求解一次&#xff0c; 下次遇到这些子问题直接取解 自底向上的方式计算最优解 2、最优子结构&#xff…

TSP问题,动态规划法

TSP问题是指旅行家要旅行n个城市&#xff0c;要求各个城市经历且仅经历一次然后回到出发城市&#xff0c;并要求所走的路程最短。各个城市间的距离可以用代价矩阵来表示。 假设从顶点i出发&#xff0c;令d(i, V)表示从顶点i出发经过V中各个顶点一次且仅一次&#xff0c;最后…

动态规划法的基本知识

一、动态规划方法相关概念 1、20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时&#xff0c;提出了著名的最优性原理(principle of optimality),同时&#xff0c;把多阶段过程转化为一系列单阶段问题&#xff0c;利用各阶…

动态规划法及其优化

在很多问题中&#xff0c;动态规划算法是我们的最优选择&#xff0c;比起递归算法&#xff0c;动态规划算法的时间复杂度和空间复杂度都更加优越&#xff0c;可以处理的数据规模更大。但是&#xff0c;动态优化算法的时间复杂度为O&#xff08;N*V&#xff09;&#xff0c;也就…

算法设计与分析之动态规划法

文章目录 前言一、动态规划法概述二、动态规划法设计思想三、动态规划法的基本要素四、动态规划算法的设计步骤五、动态规划法与分治法六、动态规划法与贪心法七、动态规划法示例总结 前言 大家好&#xff0c;我是一只勤勤恳恳的程序猿。本篇文章小猿将跟您分享算法设计与分析中…

算法-动态规划法

动态规划是在20世纪50年代由美国数学家贝尔曼为研究最优控制问题而提出的&#xff0c;当该方法在应用数学中的价值被大家认同以后&#xff0c;在计算机学界&#xff0c;动态规划法成为一种通用的算法设计技术用来求解多阶段决策最优化问题。 所以&#xff0c;同学们&#xff0…

动态规划算法

一 动态规划算法 动态规划(Dynamic Programming)算法的核心思想是&#xff1a;将大问题划分为小问题进行解决&#xff0c;从而一步步获取最优解的处理算法。 动态规划算法与分治算法类似。其基本思想也是将待求解问题分解成若干个子问题&#xff0c;先求解子问题&#xff0c;…

经典中的经典算法:动态规划(详细解释,从入门到实践,逐步讲解)

动态规划的重要性就不多说,直接进入正题 首先,我们看一下官方定义:定义: 动态规划算法是通过拆分问题&#xff0c;定义问题状态和状态之间的关系&#xff0c;使得问题能够以递推&#xff08;或者说分治&#xff09;的方式去解决。 动态规划算法的基本思想与分治法类似&#xf…

目标检测中的多尺度特征结合方式

目录 简述 解构物体检测各个阶段 FPN的演进 1&#xff09;无融合 2&#xff09;自上而下单向融合 a&#xff09;Faster/Master/Cascade RCNN中的FPN b&#xff09;RetinaNet中的FPN c&#xff09;Yolov3中的FPN 3&#xff09;简单双向融合 4&#xff09;复杂的双向融…

总结-CNN中的目标多尺度处理

Fly-AI竞赛服务平台 flyai.com 在开始学习之前推荐大家可以多在 FlyAI竞赛服务平台多参加训练和竞赛&#xff0c;以此来提升自己的能力。FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台。每周免费提供项目开源算法样例&#xff0c;支持算法能力变现以及快…

【MFEN:轻量级多尺度特征提取:SR网络】

MFEN: Lightweight multi-scale feature extraction super-resolution network in embedded system &#xff08;MFEN&#xff1a;嵌入式轻量级多尺度特征提取超分辨率网络&#xff09; 深度卷积神经网络&#xff08;CNN&#xff09;在超分辨率&#xff08;SR&#xff09;方面…

深度学习笔记---多尺度网络结构归类总结

目录 1.什么是图像金字塔 1.1 高斯金字塔 ( Gaussian pyramid): 1.2 拉普拉斯金字塔&#xff08;Laplacian pyramid&#xff09; 1.3 DOG金字塔 2. 多尺度网络&#xff08;MTCNN&#xff09; 2.1 多尺度输入网络 2.2 多尺度特征融合网络 2.2.1 并行多分支网络 2.2.2 串行…

【边缘注意:深度多尺度特征】

Learning a Deep Multi-Scale Feature Ensemble and an Edge-Attention Guidance for Image Fusion &#xff08;学习深度多尺度特征集成和图像融合的边缘注意指南&#xff09; 在本文中&#xff0c;我们提出了一种用于红外和可见光图像融合的深度网络&#xff0c;该网络将具…

多尺度特征的提取

1、图像金字塔 将图片进行不同尺度的缩放&#xff0c;得到图像金字塔&#xff0c;然后对每层图片提取不同尺度的特征&#xff0c;得到特征图。一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低&#xff0c;且来源于同一张原始图的图像集合。其通过梯次向下采样获得&…

MSRN(多尺度超分辨率重建)

目前的研究倾向于使用更深层次的卷积神经网络来提高性能。然而,盲目增加网络深度不能有效改善网络。更糟糕的是,随着网络深度的增加,训练过程中出现了更多的问题,需要更多的训练技巧。在本文中,我们提出了一种新颖的多尺度残差网络 (MSRN) 来充分利用图像特征,该网络优于…

【multi_scale】多尺度训练——目标检测训练trick

文章目录 1 多尺度训练的介绍2 代码解析3 感谢链接 1 多尺度训练的介绍 多尺度训练对全卷积网络有效&#xff0c;在训练时&#xff0c;每隔一定的 iterations&#xff0c;在一定尺寸范围内&#xff0c;随机选取一种 img_size 进行训练。通过对不同尺度的图像进行训练&#xff…

“多尺度”目标检测问题

一、“多尺度”目标检测问题简介 在目标检测任务中,被测目标的大小经常是不固定的,自动驾驶相关检测任务可能要同时检测大卡车与小狗;工业质检相关检测任务可能要同时检测布料的大面积撕裂与小穿孔;医疗病灶检测任务可能要同时检测大小不一的病灶。在被测物体尺度相差极大…

图像多尺度技术

1197 多尺度图像技术也叫做多分辨率技术&#xff08;MRA&#xff09;&#xff0c;指对图像采用多尺度的表达&#xff0c;并且在不同尺度下分别进行处理。这样做的理由是很多情况下在一种尺度中不容易看清的或者获取的特性在另外的某种尺度下就很容易发现或者是提取。所以多尺度…

目标检测中多尺度:特征金字塔FPN_Feature Pyramid Networks for Object Detection

原始内容来源于&#xff1a; https://blog.csdn.net/cdknight_happy/article/details/100528127 https://blog.csdn.net/WZZ18191171661/article/details/79494534 包含理解&#xff01; 参考文献&#xff1a;https://arxiv.org/abs/1612.03144 代码实现&#xff1a;http://ww…

MViTv2 多尺度视觉Transformer

虽然VIT&#xff08;vision transformer&#xff09;模型提出后&#xff0c;Transformer在CV领域一路攻城拔寨&#xff0c;不断刷新由自己创下的记录&#xff0c;但VIT文章中所说明的视觉领域transformer很大程度上受transformer模型平方复杂度的限制而在大尺度图像上表现不佳的…