- 浏览: 263669 次
- 性别:
- 来自: 济南
文章分类
最新评论
题目
设A1,A2,…,An为矩阵序列,Ai为Pi-1×Pi阶矩阵,i = 1,2,…,n. 确定乘法顺序使得元素相乘的总次数最少.
输入:向量P = <P0, P1, … , Pn>
实例:
P = <10, 100, 5, 50> A1: 10 × 100, A2: 100 × 5, A3: 5 × 50
乘法次序:
(A1 A2)A3: 10 × 100 × 5 + 10 ×5 × 50 = 7500
A1(A2 A3): 10 × 100 × 50 + 100 × 5 × 50 = 75000
搜索空间的规模
先将矩阵链加括号分为两部分,即P=A1*A2*...*An=(A1*A2...*Ak)*(Ak+1*...An),则有f(n)=f(1)*f(n-1)+f(2)*f(n-2)+...+f(n-1)*f(1)种方法。f(n)为一个Catalan数,所以一般的方法要计算种。
动态规划算法
输入P=< P0, P1, …, Pn>,Ai..j 表示乘积 AiAi+1…Aj 的结果,其最后一次相乘是:
m[i,j] 表示得到Ai..j的最少的相乘次数。
递推方程:
为了确定加括号的次序,设计表s[i,j],记录求得最优时最一位置。
算法递归实现
由上面的递归公式,很容易得到算法的递归实现:
const int N=5; int m[N][N]; //m[i][j]存储Ai到Aj的最小乘法次数 int s[N][N];//s[i][j]存储Ai到Aj之间加括号的位置 int RecurMatrixChain(int P[],int i,int j) { m[i][j]=100000; s[i][j]=i; if(i==j) m[i][j]=0; else{ for(int k=i;k<j;k++){ int q=RecurMatrixChain(P,i,k)+RecurMatrixChain(P,k+1,j)+P[i]*P[k+1]*P[j+1]; if(q<m[i][j]){ m[i][j]=q; s[i][j]=k; } } } return m[i][j]; } int main() { int P[N+1]={30,35,15,5,10,20}; for(int i=0;i<N;i++) m[i][i]=0; m[0][N-1]=RecurMatrixChain(P,0,N-1); return 0; }
递归实现的复杂性
复杂性满足递推关系:
由数学归纳法可得:
可见递归实现的复杂性虽然较一般算法有改进,但还是较高。分析原因,主要是子问题重复程度高。如下图所示:
1..4表示计算Ai..j中i=1,j=4的子问题,其子问题包括A1..1,而A1..2,A1..3中都包括子问题A1..1,所以很多子问题被重复计算了多次。
于是,我们想到用自底向上的迭代实现。
算法迭代实现
迭代实现主要思想是子问题由小到大,每个子问题只计算一次,并且把结果保存起来,后来用到这个子问题时,直接代入。
void MatrixChain(int P[],int n) { int r,i,j,k,t; for(i=0;i<N;i++) for(j=0;j<N;j++) m[i][j]=0; //r为当前计算的链长(子问题规模) for(r=2;r<=n;r++){ //n-r+1为最后一个r链的前边界 for(i=0;i<n-r+1;i++){ //计算前边界为r,链长为r的链的后边界 j=i+r-1; //将链ij划分为A(i) * ( (A(i+1) ... A(j) ) m[i][j]=m[i+1][j]+P[i]*P[i+1]*P[j+1]; //记录分割位置 s[i][j]=i; for( k=i+1;k<j-1;k++){ //将链ij划分为( A(i)...A(k) )* ( (A(k+1) ... A(j) ) t=m[i][k]+m[k+1][j]+P[i]*P[i+1]*P[j+1]; if(t<m[i][j]){ m[i][j]=t; s[i][j]=k; } } } } } int main() { int P[N+1]={30,35,15,5,10,20}; MatrixChain(P,N); }
迭代实现的复杂性
行7,9,16的循环为O(n),外层循环为O(1),所以算法复杂度W(n)=O(n^3)
迭代过程的一个实例
子问题由小到大的计算过程如下图所示:
结果打印
再写一个打印结果,以及打印优化函数备忘录m和标记函数的s的函数:
void PrintMatrixChain(int s[][N],int i,int j) { if (i==j) { cout<<"A"<<i+1; } else { cout<<"("; PrintMatrixChain(s, i, s[i][j]); PrintMatrixChain(s, s[i][j]+1, j); cout<<")"; } } void PrintMS(int m[][N],int s[][N],int N) { for(int r=0;r<N;r++){ for(int i=0;i<N-r;i++){ int j=i+r; cout<<"m["<<i+1<<","<<j+1<<"]="<<m[i][j]<<"\t"; } cout<<endl; } for(int r=1;r<5;r++){ for(int i=0;i<N-r;i++){ int j=i+r; cout<<"s["<<i+1<<","<<j+1<<"]="<<s[i][j]+1<<"\t"; } cout<<endl; } }
一个简单的测试实例
用一个N=5,P=<30,35,15,5,10,20>的简单实例,运行上述代码:
*注意:上述代码与解释中的下标不同,即代码中s[i-1][j-1]表示实际中的s[i,j]
参考资料:屈婉玲 刘田等 《算法设计与分析》
(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu未经允许请勿用于商业用途)
发表评论
-
unity基础开发----物体位移和旋转实用代码
2013-11-21 22:46 1221using UnityEngine; using Syst ... -
Android中View绘制优化之一---- 优化布局层次
2012-09-04 23:00 967... -
Android中View绘制优化二一---- 使用<include />标签复用布局文件
2012-09-08 13:54 971... -
Android中View绘制优化之三---- 优化View
2012-09-13 21:00 1044... -
兰林任务管理应用程序雏形版以及概要说明
2012-09-15 21:54 825... -
Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(上)
2012-10-10 18:14 1065... -
Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(下)
2012-10-17 20:05 807... -
Android中文件选择器的实现
2012-11-30 08:59 1077... -
【编译原理】使用Lex将C/C++文件输出为HTML文件
2012-07-20 09:37 97008年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ... -
【编译原理】正则表达式
2012-07-21 21:49 213208年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ... -
【OpenCV】访问Mat图像中每个像素的值
2012-07-22 07:10 1089今天百度搜资料还搜到了自己的。。。《访问图像中每个像素的值 ... -
【编译原理】用Yacc做语法分析
2012-07-23 05:47 169408年9月入学,12年7月毕 ... -
【UML】UML几种图的绘制
2012-07-24 09:49 93708年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ... -
【OpenCV】邻域滤波:方框、高斯、中值、双边滤波
2012-07-26 10:52 1406邻域滤波(卷积) 邻域算子值利用给定像素 ... -
【数据结构】排序算法:希尔、归并、快速、堆排序
2012-07-28 06:15 93708年9月入学,12年7月毕 ... -
【OpenCV】角点检测:Harris角点及Shi-Tomasi角点检测
2012-07-31 13:25 1489角点 特征检测与匹配 ... -
【UML】案例分析:机场运作系统
2012-08-01 17:22 292008年9月入学,12年7月毕 ... -
【OpenCV】边缘检测:Sobel、拉普拉斯算子
2012-08-04 13:41 1465边缘 边缘(edge)是指图像局部强度变化最显著的部分。主要 ... -
【OpenCV】Canny 边缘检测
2012-08-08 10:17 1933Canny 边缘检测算法 1986 ... -
【UML】案例分析:新型超市购物自助系统
2012-08-19 01:13 125608年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ...
相关推荐
解大整数 矩阵 乘法 算法设计 实验报告与源代码工程
算法设计与分析实验,Strassen矩阵乘法,java实现,输入矩阵阶数后由系统自动生成两个矩阵,然后用Strassen方法,和普通方法分别计算乘法结果。
Strassen's的矩阵乘法算法的实现
矩阵乘法(分治法)内附实验报告 算法设计与分析
OpenBLAS项目与矩阵乘法优化设计算法实现细节
首先,在可扩展矩阵乘法算法(SMM)算法枢轴行和枢轴列通信研究基础上,利用分层方式在更高等级上对网格进行矩形群划分,实现矩阵乘法的二维计算向三维计算转变,并设计对应的集群内通信和集群间通信过程,实现SMM...
数字系统设计:矩阵乘法的并行算法分析.ppt
2.5 Strassen矩阵乘法 2.6 棋盘覆盖 2.7 合并排序 2.8 快速排序 2.9 线性时间选择 2.10 最接近点对问题 2.11 循环赛日程表 习题2 第3章 动态规划 3.1 矩阵连乘问题 3.2 动态规划算法的基本要素 3.3 最长公共子序列 ...
分治法实现矩阵相乘
你的任务是要确定矩阵连乘的运算次序,使计算这n个矩阵的连乘积A1A2…An时总的元素乘法次数达到最少。 例如:3个矩阵A1,A2,A3,阶分别为10×100、100×5、5×50,计算连乘积A1A2A3时按(A1A2)A3所需的元素乘法...
关于运用动态规划解决矩阵链乘法问题的具体步骤
使用Hadoop MapReduce实现两个矩阵相乘算法
C#程序 算法设计与分析 分治法 Strassen矩阵乘法
Strassen矩阵乘法算法的CUDA实现。
【P147页 5.4.2 Strassen矩阵乘法】的 Mathematica 计算验证.nb 是 Mathematica12.1的编程代码验证,Mathematica符号计算语言简洁明了! 欢迎进行下载验证!
矩阵类设计,求逆矩阵的算法,利用类的思想进行乘法,加法,求逆矩阵
矩阵连乘积的动态规划算法设计;确定n个矩阵连乘积 A_1 A_2 A_3…A_n 的计算次序,使得按照这一次序计算矩阵连乘积,需要的"数乘"次数最小。
1、资源内容:基于Hadoop MapReduce的矩阵乘法 2、代码特点:内含运行结果,不会运行可私信,参数化编程、参数可方便更改、代码编程思路清晰、注释明细,都经过测试运行成功,功能ok的情况下才上传的。 3、适用对象...
通过分析分组密码算法中矩阵乘法运算的设计原理和特点,结合逻辑电路结构特征,提出一种可重构矩阵乘法硬件架构的设计原理及方法.电路模拟结果显示,按此原理设计的运算电路在保持运算电路高效性的同时,提高了硬件电路...
第6章到第9章分别给出了几个领域的算法,如序列和集合的算法(排序、序列比较、匹配等)、几何算法(凸包和交集问题等)、代数和数值算法(矩阵乘法、快速傅里叶变换等);第10章涉及归约或约简,也是第11章的序幕,...