算法设计:实验三动态规划法

2024-08-28 23:52

本文主要是介绍算法设计:实验三动态规划法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【实验目的】

应用动态规划算法思想求解矩阵连乘的顺序问题。

【实验要求】         

应用动态规划算法的最优子结构性质和子问题重叠性质求解此问题。分析动态规划算法的基本思想,应用动态规划策略写出算法及相应的程序,求解此题。要读懂读透A[i,j],

A[1,n]=A[1,k] ×A[k+1,n],m[i][j],s[i][j]各式所表达的含义并正确加以应用。m[i][j]的递归定义:

要求完成:⑴算法描述⑵写出程序代码⑶完成调试⑷进行过程与结果分析。

【实验内容】

对于下列所描述的问题,给出相应的算法描述,并完成程序实现与时间复杂度的分析。该问题描述为:一般地,考虑矩阵A1,A2,… ,An的连乘积,它们的维数分别为d0,d1,…,dn,即Ai的维数为di-1×di  (1≤i≤n)。确定这n个矩阵的乘积结合次序,使所需的总乘法次数最少。对应于乘法次数最少的乘积结合次序为这n个矩阵的最优连乘积次序。按给定的一组测试数据对根据算法设计的程序进行调试:6个矩阵连乘积A=A1×A2×A3×A4×A5×A6,各矩阵的维数分别为:A1:10×20,A2:20×25,A3:25×15,A4:15×5,A5:5×10,A6:10×25。完成测试。

【算法思想及处理过程】

动态规划(Dynamic Programming,简称 DP)是一种通过将原问题分解为相互重叠的子问题,并通过对这些子问题的解进行存储和复用,从而避免重复计算,以提高算法效率的方法。其基本思想是利用子问题的最优解构建原问题的最优解,通过填表格或者使用递归加记忆化的方法来实现。

在矩阵连乘最优化问题中,动态规划的基本思想是:

问题拆解:

将原问题拆解为子问题。对于矩阵连乘问题,给定一系列矩阵 A1, A2, ..., An,每个矩阵 Ai 的维度为 di-1 x di,目标是找到一种矩阵相乘的顺序,使得总的乘法次数最少。这个问题可以拆解为子问题:对于任意子链 Ai x ... x Aj,找到其最优的连乘次序。

定义状态:

定义状态 m[i][j],表示矩阵链 Ai x ... x Aj 的最优乘法次数。同时定义 s[i][j],表示最优的分割点,即在哪里将链 Ai x ... x Aj 分割成两部分进行连乘。

递推关系:

通过递推关系式来计算 m[i][j] 的值,即:

其中 d_{i-1} x d_k x d_j 是将两部分子链 Ai x ... x Ak 和 Ak+1 x ... x Aj 连乘的乘法次数。

填表:

使用动态规划的方法填充表格 m[i][j] 和 s[i][j],首先填充长度为 1 的链(单个矩阵的情况),再逐步增加长度,直至填满整个表格。

构造解:

根据填表得到的 s[i][j],通过递归或迭代的方式构造出最优的连乘次序。

综上所述,动态规划解决矩阵连乘最优化问题的基本思路是利用子问题的最优解构建原问题的最优解,通过填表格并使用递推关系来计算最优解的值,最终通过构造解得到最优的矩阵连乘次序。

以下是确定最优解的流程图:

主要思路为计算m时只需要m的左边与下边的数组值,所以可以从下至上,从左至右计算。

以下是打印最优连乘矩阵次序函数流程图:

递归终止条件:

首先,递归函数 printOptimal 需要处理递归的终止条件。当 i == j 时,表示当前子链只有一个矩阵,此时直接打印该矩阵的名称即可,因为不需要再进行连乘,已经是最小单位了。

利用 s 数组确定分割点:

对于子链 Ai x ... x Aj,s[i][j] 记录了使得乘法次数最少的分割点 k。因此,在递归调用中,我们首先根据 s[i][j] 将当前子链分成两部分:

第一部分:从 i 到 s[i][j] 的子链

第二部分:从 s[i][j] + 1 到 j 的子链

这样可以保证递归地构建出最优的连乘次序。

递归调用:

在分割好子链之后,递归地调用 printOptimal 函数:

对于第一部分:调用 printOptimal(matrices, s, i, s[i][j])

对于第二部分:调用 printOptimal(matrices, s, s[i][j] + 1, j)

这样可以递归地将整个矩阵连乘问题拆解为更小规模的子问题,直到达到终止条件为止。

输出格式控制:

在递归调用结束后,根据递归的层级,添加括号和矩阵名称,以构建出最优的连乘次序表达式。

【程序代码】

#include <stdio.h>
#include <limits.h>
#include <string.h>#define MAX_SIZE 100
#define MAX 9999999 typedef struct {char name[20];int rows;int cols;
} Matrix;// 计算最优连乘矩阵次序
void matrixOptimal(Matrix matrices[], int num, int m[MAX_SIZE][MAX_SIZE], int s[MAX_SIZE][MAX_SIZE]) {int i,j,k,l,flag;for (i = 1; i <= num; i++) {m[i][i] = 0;}// 计算子问题的最优解 for(j = 1; j <= num; j++){for(i = j-1;i > 0; i--){m[i][j] = MAX;for (k = i; k < j; k++) {flag = m[i][k] + m[k+1][j] + matrices[i].rows * matrices[k].cols * matrices[j].cols;if (flag < m[i][j]) {m[i][j] = flag;s[i][j] = k;}}}}/*for (l = 2; l <= num; l++) {  // l 为连乘链的长度for (i = 1; i <= num - l + 1; i++) {j = i + l - 1;m[i][j] = MAX;for (k = i; k < j; k++) {flag = m[i][k] + m[k+1][j] + matrices[i].rows * matrices[k].cols * matrices[j].cols;if (flag < m[i][j]) {m[i][j] = flag;s[i][j] = k;}}}}*/
}// 打印最优连乘矩阵次序
void printOptimal(Matrix matrices[], int s[MAX_SIZE][MAX_SIZE], int i, int j) {if (i == j) {printf("%s", matrices[i].name);} else {printf("(");printOptimal(matrices, s, i, s[i][j]);printOptimal(matrices, s, s[i][j] + 1, j);printf(")");}
}int main() {Matrix matrices[MAX_SIZE];int num;int i,j;printf("输入矩阵个数:");scanf("%d", &num);printf("输入每个矩阵的名称和维度:\n");for (i = 1; i <= num; i++) {printf("矩阵 %d名称: ", i);scanf("%s", matrices[i].name);printf("维数: ");scanf("%d %d", &matrices[i].rows, &matrices[i].cols);// 对第一个矩阵不进行维度检查 if (i > 1) {if (matrices[i-1].cols != matrices[i].rows) {printf("错误:矩阵维度不匹配,请重新输入。\n");i--;}}}int m[MAX_SIZE][MAX_SIZE];  // 存储最小乘法次数int s[MAX_SIZE][MAX_SIZE];  // 存储最优分割点matrixOptimal(matrices, num, m, s);printf("------------------------------------");printf("\n数组 m:\n");for (i = 1; i <= num; i++) {for (j = 1; j <= num; j++) {printf("%d\t", m[i][j]);}printf("\n");}printf("\n数组 s:\n");for (i = 1; i <= num; i++) {for (j = 1; j <= num; j++) {printf("%d\t", s[i][j]);}printf("\n");}printf("------------------------------------\n");printf("所需的总乘法次数为:%d\n", m[1][num]);printf("最优连乘积次序为:");printOptimal(matrices, s, 1, num);printf("\n");return 0;
}

【运行结果】

【算法分析】

算法思路:

这个算法利用动态规划的思想解决矩阵连乘最优化问题。首先,通过 matrixOptimal 函数计算出最小乘法次数 m[i][j] 和最优分割点 s[i][j],然后通过 printOptimal 函数根据 s 数组打印出最优的连乘次序。

时间复杂度分析:

计算 m[i][j] 和 s[i][j] 的时间复杂度:

外层循环 for (j = 1; j <= num; j++) 循环次数为 num,内层循环 for (i = j-1; i > 0; i--) 的平均循环次数约为 num/2。内部的循环 for (k = i; k < j; k++) 的循环次数约为 j - i,因此计算 m[i][j] 和 s[i][j] 的时间复杂度大致为 O(num^3)。

打印最优连乘次序的时间复杂度:

printOptimal 函数的时间复杂度主要取决于矩阵链的长度 num,递归调用的次数是 O(num),因此其时间复杂度也是 O(num)。

总体时间复杂度:

综合考虑,整个算法的时间复杂度主要由计算 m[i][j] 和 s[i][j] 的过程决定,即 O(num^3)。其余部分包括输入矩阵信息和打印结果的时间复杂度较小,对总体复杂度影响较小。

因此,该算法的时间复杂度为 O(num^3),其中 num 是矩阵的个数。对于较大的矩阵个数,算法的执行时间会随着 num 的增加而增加。需要注意的是,在实际应用中,可以考虑优化算法以降低时间复杂度,例如通过记忆化搜索等方法减少重复计算,或者使用更高效的算法来解决矩阵连乘问题。

这篇关于算法设计:实验三动态规划法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1116249

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry