动态规划与分治法的异同:

相同点:其基本思想都是将待求解问题分解为若干子问题,先求解子问题,再结合这些子问题的解得到原问题的解。

差异点:与分治法不同的是,适合用动态规划法求解的问题经分解得到的子问题往往不是相互独立的。有些问题分解后的子问题往往是重复的,此时若用分支法则会重复计算耗费时间内存。

总结:为了达到避免重复计算,可以用一个表来记录所有已解决的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。

步骤

  1. 找出最优解的性质,刻画其结构特征。
  2. 递归地定义最优值。
  3. 以自底向上的方式计算最优值。
  4. 根据计算最优值得到的信息构造最优解。

矩阵连乘问题

  1. 分析最优解的结构
  2. 建立递归关系
  3. 计算最优值
  4. 构造最优解

动态规划算法的基本要素

最优子结构:当问题的最优解包含了其子问 题的最优解时,称该问题具有最优子结构性质。

重叠子问题:在用递归算法自顶向下解此问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算。动态规划算法对每个子问题只解一次,然后将解保存在一个表格中。


问题描述:

给定n个矩阵:A1,A2,…,An,其中Ai与Ai+1是可乘的,i=1,2…,n-1。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。

问题解析:

由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。这种计算次序可以用加括号的方式来确定。若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。

例如,矩阵连乘积A1A2A3A4有5种不同的完全加括号的方式:(A1(A2(A3A4))),(A1((A2A3)A4)),((A1A2)(A3A4)),((A1(A2A3))A4),(((A1A2)A3)A4)。每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。

有点需要记住,两个矩阵相乘之后得到的矩阵的行为前面一个矩阵的行,列为后面一个矩阵的列,复杂度与第一个矩阵的列也有关。

递推规律:

设计算A[i:j](矩阵A从i乘到j),1≤i≤j≤n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n](上面例题就是m[1][6])。

  当i=j时,A[i:j]=Ai,因此,m[i][i]=0,i=1,2,…,n
  当i<j时,若A[i:j]的最优次序在Ak和Ak+1之间断开,i<=k<j,则:m[i][j]=m[i][k]+m[k+1][j]+pi-1pkpj。由于在计算是并不知道断开点k的位置,所以k还未定。不过k的位置只有j-i个可能。因此,k是这j-i个位置使计算量达到最小的那个位置。

  综上,有递推关系如下:



代码如下:

#include<iostream>
using namespace std;#define N 7  //N为7,实际表示有6个矩阵
/*
*矩阵链构造函数:构造m[][]和s[][]
*m中存储的值是计算出来的最小乘法次数,比如m[1][5]就是A1A2A3A4A5的最小乘法次数
*s中存储的是获取最小乘法次数时的断链点,s[1][5]对应的就是如何拆分A1A2A3A4A5,
*比如S[1][5]=3可表示:(A1A2A3)(A4A5),当然内部断链还会继续划分A1A2A3
*/
int MatrixChain(int *p, int n, int m[][N], int s[][N]){for(int i=1;i<=n;i++){     //矩阵链中只有一个矩阵时,次数为0,注意m[0][X]时未使用的m[i][i]=0;}for(int r=2;r <= n;r++){    //矩阵链长度,从长度为2开始for(int i=1;i <= n-r+1;i++){    //根据链长度,控制链最大的可起始点int j = i+(r-1);  //矩阵链的末尾矩阵,注意r-1,因为矩阵链为2时,实际是往右+1m[i][j] = m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];   //先设置最好的划分方法就是直接右边开刀,后续改正,也可合并到下面的for循环中s[i][j]=i;for(int k=i+1;k < j;k++){   //这里面将断链点从i+1开始,可以断链的点直到j-1为止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;}}}}
}
/*
*追踪函数:根据输入的i,j限定需要获取的矩阵链的始末位置,s存储断链点
*/
void Traceback(int i,int j, int s[][N]){if(i==j)       //回归条件{cout<<"A"<<i;}else       //按照最佳断点一分为二,接着继续递归{cout<<"(";Traceback(i,s[i][j],s);Traceback(s[i][j]+1,j,s);cout<<")";}
}
int main(){int p[N]={30,35,15,5,10,20,25};int m[N][N],s[N][N];MatrixChain(p,N-1,m,s);//N-1因为只有六个矩阵Traceback(1,6,s);return 0;
}

运行结果:


备忘录方法:


代码如下:

#include<iostream>
using namespace std;#define N 7  //N为7,实际表示有6个矩阵
int p[N]={30,35,15,5,10,20,25};
int m[N][N],s[N][N];
int LookupChain(int i, int j){if(m[i][j]>0)return m[i][j];if(i == j)return 0;m[i][j] = 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<m[i][j]){m[i][j]=t;s[i][j]=k;}}return m[i][j];
}int MemorizedMatrixChain(int n, int m[][N], int s[][N]){for(int i=1;i<=n;i++){  //初始化默认都是0for(int j=1;j<=n;j++)m[i][j] = 0;}return LookupChain(1,n);
}
/*
*追踪函数:根据输入的i,j限定需要获取的矩阵链的始末位置,s存储断链点
*/
void Traceback(int i,int j, int s[][N]){if(i==j)       //回归条件{cout<<"A"<<i;}else       //按照最佳断点一分为二,接着继续递归{cout<<"(";Traceback(i,s[i][j],s);Traceback(s[i][j]+1,j,s);cout<<")";}
}
int main(){MemorizedMatrixChain(N-1,m,s);//N-1因为只有六个矩阵Traceback(1,6,s);return 0;
}

运行结果:

【史上最详细】动态规划:矩阵连乘问题(C++实现,含备忘录方法)相关推荐

  1. 史上最详细全中文 Cisco 3560交换机使用手册

    史上最详细全中文 Cisco 3560交换机使用手册 (末尾送交换机安全技术) 目 录 CISCO Catalyst 3560-E系列交换机的功能应用及安全解决方案 3 一.Cisco? Cataly ...

  2. 背包算法(一)-01背包-史上最详细解答

    背包算法(一)-01背包-史上最详细解答 1. 题目 2. 分析 2.1 状态表示 2.2 状态计算 3. 实现 4. 优化 5. 测试 1. 题目 问题描述:有n件物品和容量为m的背包,给出i件物品 ...

  3. 史上最详细的微生物扩增子数据库整理

    声明:文件所有链接内容来自"生信控"公众号,已经获作者向屿授权. 本人对每个数据库的使用目的和经验配导读,需要使用的小伙伴读点击链接跳转原文学习. "生信控"相 ...

  4. 史上最详细版Centos6安装详细教程

    镜像CentOS-6.8-x86_64-bin-DVD1.ISO 将下载好的镜像上传到服务器,并选择该镜像(详情请看上篇exsi镜像上传文章) 一.安装开始 开机选择第一项 这里询问我们是否要对光盘进 ...

  5. 史上最详细“截图”搭建Hexo博客——For Windows

    http://angelen.me/2015/01/23/2015-01-23-%E5%8F%B2%E4%B8%8A%E6%9C%80%E8%AF%A6%E7%BB%86%E2%80%9C%E6%88 ...

  6. 不仅有史上最详细Docker 安装Minio Client,还附带解决如何设置永久访问和永久下载链接!!(详图)绝对值得收藏的哈!!!!

    背景: 这两天在整理知识点,然后在学习Minio,一开始遇到更新,整了我不少时间,之前用的太久了,改了不少东西.用了之后发现不知道怎么设置成永久访问,就出了这篇文章. 史上最详细Docker安装最新版 ...

  7. 史上最详细Docker安装最新版Minio 带详解 绝对值得收藏!!! 让我们一起学会使用minio搭建属于自己的文件服务器!!走上白嫖之路!解决启动了但是浏览器访问不了的原因

    让我们一起学会使用minio搭建属于自己的文件服务器!!走上白嫖之路! WARNING: Console endpoint is listening on a dynamic port (34451) ...

  8. 史上最详细阿里云服务器上Docker部署War包项目 实战每一步都带详细图解!!!

    史上最详细阿里云服务器上Docker部署War包项目 实战每一步都带详细图解!!! 部署jar 包方式: https://blog.csdn.net/weixin_45821811/article/d ...

  9. 史上最详细的Android Studio系列教程四--Gradle基础

    史上最详细的Android Studio系列教程四--Gradle基础 转载于:https://www.cnblogs.com/zhujiabin/p/5125917.html

  10. 史上最详细的MySQL操作事例

    史上最详细的MySQL操作事例 文章目录 史上最详细的MySQL操作事例 一.数据库的操作 二.数据表的操作 三.数据表的增删查该 四.数据准备 五.条件查询 六.排序 七.聚合函数 八.分组 九.分 ...

最新文章

  1. CSS实现文字环绕图片
  2. python 反转链表
  3. MAVEN_OPTS=-Xms128m -Xmx512m
  4. VTK:InfoVis之SCurveSpline
  5. 【安全测试】:某系统短信修改密码,绕过逻辑漏洞
  6. LeetCode OJ - Best Time to Buy and Sell Stock II
  7. Illustrator 教程,如何在 Illustrator 中创建和编辑图层?
  8. tarjan 割点 割边
  9. Cmakelists 与gcc 调用so库文件,几个名词解释
  10. C中常量数组不能修改
  11. 科大讯飞 离线语音识别python_用Python来使用科大讯飞语音识别,so easy
  12. 从 Resource Hacker 到 Heaventools PE Explorer 1.99 R6
  13. LeetCode | 521. Longest Uncommon Subsequence I
  14. 手zhuan手机软件app下载排行网站源码(需要自取)
  15. 《Python全栈系列教程》目录
  16. BICC协议(简介)
  17. Java网络编程之实现资源下载详解【王道Java】
  18. 必须要了解的物联网安全知识
  19. VMware ESXi启动卡在 vmkibft loaded successfully
  20. 王怀南+邵亦波+王建硕=?

热门文章

  1. Linux 多线程(二)线程安全:线程安全、互斥与互斥锁、死锁、同步与条件变量
  2. python爬取糗事百科
  3. “保持耐心”,永远从用户角度出发— 专访阿里巴巴淘系技术内容中台负责人吴桂林(梁舒)...
  4. BBR如何让Spotify流媒体更流畅?
  5. 首届Elastic社区技术大会隆重开幕!腾讯分享2场中文演讲
  6. Go netpoller 网络模型之源码全面解析
  7. 可能是世界上最简单的用 Go 来写 WebAssembly 的教程
  8. 微信扫一扫识物的技术揭秘:抠图与检索
  9. Yacc 与 Lex 快速入门
  10. Dubbo 一篇文章就够了:从入门到实战