目录:矩阵连乘问题:1. 描述矩阵连乘问题2. 分析矩阵连乘问题以及对递归式的推导(1)直接递归思路(2)备忘录思路(3)动态规划思路3. 伪代码的方式描述算法:(1)直接递归算法(2)备忘录算法(3)动态规划算法4. 把算法转换成程序实现的过程及结果(1)直接递归算法程序(2)备忘录算法程序(3)动态规划算法程序1.描述矩阵连乘问题:给定n 个矩阵{n A A A ⋯,2,1},其中i A 和1+i A 是可乘的,i=1,2,…,n-1。
考察这n 个矩阵的连乘积n A A A ⋯,2,1。
由于矩阵乘法具有结合律,故计算矩阵的连乘积可以有许多不同的计算次序。
这种计算次序可以用加括号的方式来确定。
若一个矩阵连乘积的计算次序完全确定,也就是说连乘积已完全加括号,则可依次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。
完全加括号的矩阵连乘可递归地定义为:(1)单个矩阵是完全加括号的;(2)矩阵连乘积A 是完全加括号的,则A 可表示为2个完全加括号的矩阵连乘B 和C 的乘积并加括号,即A=(BC )。
矩阵A 和B 可乘的条件是矩阵A 的列数等于矩阵B 的行数。
若A 是一个p ×q 的矩阵,B 是一个q ×r 的矩阵,那么C=A ×B 就是一个p ×r 矩阵。
它的计算是三重循环的,计算量是pqr 。
如果加括号后矩阵的量是不同的,所以我们的问题就是要讨论如何给连乘的矩阵加括号才能使矩阵的计算量最少。
穷举搜索法:对于n 个矩阵的连乘积,设有不同的计算次序P(n)。
由于可以先在第k 个和第k+1个矩阵之间将原矩阵序列分为两个矩阵子序列,k=1,2,...,n-1;然后分别对这两个矩阵子序列完全加括号;最后对所得的结果加括号,得到原矩阵序列的一种完全加括号方式。
由此可得P(n)的递归式如下:1 n=1 P (n )=∑-=-11)()(n k k n P k P n>1解此递归方程可得,P(n)=C(n-1),而C(n)是一个指数增长的函数。
因此穷举搜索法不是一个有效的算法。
以下将用三种方法来解决矩阵连乘问题的最优加括号方式以及最优解。
2. 分析矩阵连乘问题以及对递归式的推导将矩阵连乘积j i i A A A ⋯+,1,简记为A[i:j]。
考察计算A[1:n]的最优计算次序。
这个问题的一个关键特征是:计算A[1:n]的最优次序包含的计算矩阵子链A[1:k]和A[k+1:n]的次序也是最优的。
这是因为:定义矩阵A i 的维数为p i-1×p i ,则A[i:k]的计算次数为p i-1×p k ,A[k+1,j]的计算次数为p k ×p j ,而这两个总的矩阵最后相乘时的计算量是固定的,为p i-1×p k ×p j 。
所以,矩阵连乘计算次序问题的最优解包含着其子问题的最优解。
这种性质称为最优子结构性质。
(1)、直接递归的思路:记计算A[i:j],1≤i ≤j ≤n ,所需最少数乘次数为m[i][j],则原问题的最优质为m[1][n]。
由分析得知:m[i][j]可以递归的定义为:0 i=j m[i][j]= }]][1[]][[{min 1j k i jk i p p p j k m k i m -≤≤+++ i<jm[i][j]给出了最优值,即计算A[i][j]所需的最少数乘次数。
同时还确定了计算A[i :j]的最优次序中的断开位置k ,也就是说,对于这个k 有m[i][j]=jk i p p p j k m k i m 1]][1[]][[-+++若将对应于m[i][j]的断开位置k 记s[i][j],在计算出最优值m[i][j]后,可递归地由s[i][j]构造出相应的最优解。
可以证明该算法的计算时间T(n)有指数下界,由算法的递归部分可得: O(1) n=1 T(n)≥1+∑-=+-+11)1)()((n k k n T k T n>1因此,当n>1时,T(n)≥n+2∑-=11)(n k k T据此,可用数学归纳法证明T(n)≥2n-1=)2(nΩ。
直接递归法的计算时间随n 的增长指数增长。
(2)、备忘录方法的思路:备忘录方法为每个子问题建立一个记录项,初始化时,该记录项存入一个特殊的值,表示该问题尚未求解。
在求解过程中,对每个待求的子问题,首先查看其相应的记录项。
若记录项中存储的是初始化时存入的特殊值,则表示该问题第一次遇到,此时计算出该子问题的解,并保存在相应的记录项中,以备以后查看。
若记录项中存储的不是初始化存入的特殊值,(比如初始化为-1,解答后赋值为0),则表示该问题已被计算过,其相应的记录项中存储的应该是该子问题的解答。
此时,只要从记录相中取出该子问题的解答即可,而不必重新计算。
备忘录方法的计算量:因为是要计算m[i][j], 因此只要从n 个变量中任意选出2个分别作为i ,j ,则共有2n C 种选法,即有2n C 个子问题;当i=j 时有n 种选法,所以总的子问题就为:2nC +n=2)1(+n n 个。
每填入一个记录项,就要花费O (n )的时间,所以备忘录方法的时间复杂度为O(n 3)。
注意,在m[i][j]中,如果i>j 是没有意义的,因此在表格中都即为x ;而且,如果i=j ,则代表单个矩阵,所以m[i][i]=1. 根据直接递归的方法的思路,如果要求m[i][j],就必须要求m[i][k]和m[k+1][j],根据m[i][j]的矩阵,则如果要求解m[1][2],则需要知道m[1][1]和m[1][2];如果要求解m[1][3],则要知道m[1][1]、m[1][2]和m[1][1]和m[2][3];以此类推。
通过此规律可以总结出要求某一个元素,就动态规划算法的计算量主要取决于程序中对行、列和加括号的位置k 的三重循环。
循环体内的计算量为O(1),而三重循环的总次数为O(n3)。
因此该算法的计算时间上界为O(n3)。
和备忘录的算法的时间复杂度一样,都比直接递归的穷举搜索法有效得多。
3. 伪代码的方式描述算法:(1)直接递归算法:int RecurMatrixChain(int i,int j){if(i==j) return 0;int u=RecurMatrixChain(i,i)+RecurMatrixChain(i+1,j)+p[i-1]*p[i]*p[j];int n;忘录算法"<<endl;cout<<"2.直接递归算法"<<endl;cout<<"3.动态规划算法"<<endl;cout<<"4.重新输入矩阵"<<endl;cout<<"5.退出程序"<<endl;cout<<endl;cout<<"请输入选择的编号:";cin>>choice;cout<<endl;while(choice!=5){switch(choice){case 1:LookupChain(1,n);cout<<"动态规划算法:"<<endl;cout<<"矩阵连乘的最优值为:"<<m[1][n]<<endl;cout<<"矩阵连乘的最优解为:";Traceback(1,n);cout<<endl;break;case 2:RecurMatrixChain(0,n);cout<<"动态规划算法:"<<endl;cout<<"矩阵连乘的最优值为:"<<m[1][n]<<endl;cout<<"矩阵连乘的最优解为:";Traceback(1,n);cout<<endl;break;case 3:MatrixChain();cout<<"动态规划算法:"<<endl;cout<<"矩阵连乘的最优值为:"<<m[1][n]<<endl;cout<<"矩阵连乘的最优解为:";Traceback(1,n);cout<<endl;break;case 4:goto L;break;case 5:choice=4;break;default:break;}cout<<endl;cout<<"请选择矩阵连乘的算法:"<<endl;cout<<"1.备忘录算法"<<endl;cout<<"2.直接递归算法"<<endl;cout<<"3.动态规划算法"<<endl;cout<<"4.重新输入矩阵"<<endl;cout<<"5.退出程序"<<endl;cout<<"请输入选择的编号:";cin>>choice;cout<<endl;}cout<<endl;return 0;}运行结果:。