矩阵连乘最佳加括号方式-动态规划算法

合集下载

动态规划法解矩阵连乘问题

动态规划法解矩阵连乘问题

动态规划法解矩阵连乘问题实验内容给定n个矩阵{A1,A2,….An},其中Ai与Ai+1是可乘的,i=1,2,3。

,n-1。

我们要计算这n个矩阵的连乘积。

由于矩阵乘法满足结合性,故计算矩阵连乘积可以有许多不同的计算次序。

这种计算次序可以用加括号的方式确定。

若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则我们可依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。

解题思路将矩阵连乘积A(i)A(i+1)…A(j)简记为A[i:j],这里i <= j 。

考察计算A[i:j]的最优计算次序。

设这个计算次序在矩阵A(k)和A(k+1)之间将矩阵链断开,i <= k < j, 则其相应完全加括号方式为(A(i)A(i+1) …A(k)) * (A(k+1)A(k+2) …A(j))。

特征:计算A[i:j]的最优次序所包含的计算矩阵子链A[i:k]和A[k+1:j]的次序也是最优的。

矩阵连乘计算次序问题的最优解包含着其子问题的最优解。

设计算A[i:j] , 1 <= i <= j <= n ,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1, n]当i = j 时,A[i:j]=Ai ,因此,m[i,i] = 0 , i = 1,2, …,n当i < j 时,m[i,j] = m[i,k] + m[k+1,j] + p(i-1)p(k)p(j) 这里A(i)的维数为p(i-1)*(i)( 注:p(i-1)为矩阵A(i)的行数,p(i)为矩阵A[i]的列数)实验实验代码#in elude <iostream>#in elude <vector>using n amespaee std ;class matrix_cha in{public:matrix_eha in(const vector <int> & c){ cols = c ;count = cols.size (); mc.resize (co unt);s.resize (co unt);for (i nt i = 0; i < count; ++i) { mc[i].resize (co unt); s[i].resize (co unt);}for (i = 0; i < count; ++i) { for (int j = 0; j < count; ++j) { mc[i][j] = 0 ;s[i][j] = 0 ;//记录每次子问题的结果void lookup_cha in () {__lookup_cha in (1, count - 1);min_count = mc[1][co unt - 1];cout << "min _multi_co unt = "<< min_count << endl ;//输出最优计算次序__trackback (1, count - 1);}//使用普通方法进行计算void calculate () {int n = count - 1; //矩阵的个数// r表示每次宽度// i,j表示从从矩阵i到矩阵j// k表示切割位置for (i nt r = 2; r <= n; ++ r) {for (int i = 1; i <= n - r + 1; ++ i) {int j = i + r - 1 ;//从矩阵i到矩阵j连乘,从i的位置切割,前半部分为0mc[i][j] = mc[i+1][j] + cols[i-1] * cols[i] * cols[j];s[i][j] = i ;for (int k = i + 1; k < j; ++ k) {int temp = mc[i][k] + mc[k + 1][j] +cols[i-1] * cols[k] * cols[j];if (temp < mc[i][j]) {mc[i][j] = temp ;s[i][j] = k ;}} // for k} // for i} // for rmin_count = mc[1][ n];cout << "min _multi_co unt = "<< min_count << endl ;//输出最优计算次序__trackback (1, n);private:int __lookup_cha in (int i, i nt j) {//该最优解已求出,直接返回if (mc[i][j] > 0) {return mc[i][j];}if (i == j) {return 0 ; //不需要计算,直接返回}//下面两行计算从i到j按照顺序计算的情况int u = __lookup_cha in (i, i) + __lookup_cha in (i + 1, j)+ cols[i-1] * cols[i] * cols[j];s[i][j] = i ;for (int k = i + 1; k < j; ++ k) {int temp = __lookup_cha in (i, k) + __lookup_cha in(k + 1, j)+ cols[i - 1] * cols[k] * cols[j];if (temp < u) {u = temp ;s[i][j] = k ;}}mc[i][j] = u ;return u ;}void __trackback (int i, i nt j) {if (i == j) {return ;}__trackback (i, s[i][j]);__trackback (s[i][j] + 1, j);cout <<i << "," << s[i][j] << " " << s[i][j] + 1 << "," << j << endl;}private:vector<int> cols ; // 列数int count ; // 矩阵个数+ 1vector<vector<int> > mc; //从第i个矩阵乘到第j个矩阵最小数乘次数vector<vector<int> > s; //最小数乘的切分位置int min_count ; //最小数乘次数};int mai n(){//初始化con st i nt MATRIX_COUNT = 6 ;vectorvi nt> c(MA TRIX_COUNT + 1);c[0] = 30 ;c[1] = 35 ;c[2] = 15 ;c[3] = 5 ;c[4] = 10 ;c[5] = 20 ;c[6] = 25 ;matrix_cha in me (c); // mc.calculate (); mc」o okup_cha in (); return 0 ;}实验结果实验验证从s 可知计算顺序为((A1(A2A3))((A4A5))A6))实验总结在这次实验中懂得了动态规划法运用方法和解题思路的重要性,在这个程序中如何 建立动态规划的过程建立递归过程 保存已解决的子问题答案。

算法设计与分析——矩阵连乘问题(动态规划)

算法设计与分析——矩阵连乘问题(动态规划)

算法设计与分析——矩阵连乘问题(动态规划)⼀、问题描述引出问题之前我们先来复习⼀下矩阵乘积的标准算法。

int ra,ca;//矩阵A的⾏数和列数int rb,cb;//矩阵B的⾏数和列数void matrixMultiply(){for(int i=0;i<ra;i++){for(int j=0;j<cb;j++){int sun=0;for(int k=0;k<=ca;k++){sum+=a[i][k]*b[k][j];}c[i][j]=sum;}}}给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。

如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

例如,给定三个连乘矩阵{A1,A2,A3}的维数分别是10*100,100*5和5*50,采⽤(A1A2)A3,乘法次数为10*100*5+10*5*50=7500次,⽽采⽤A1(A2A3),乘法次数为100*5*50+10*100*50=75000次乘法,显然,最好的次序是(A1A2)A3,乘法次数为7500次。

加括号的⽅式对计算量有很⼤的影响,于是⾃然地提出矩阵连乘的最优计算次序问题,即对于给定的相继n个矩阵,如何确定矩阵连乘的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

⼆、问题分析矩阵连乘也是Catalan数的⼀个常⽤的例⼦,关于时间复杂度的推算需要参考离散数学关于Catalan的内容。

下⾯考虑使⽤动态规划法解矩阵连乘积的最优计算次序问题。

1、分析最优解的结构问题的最优⼦结构性质是该问题可以⽤动态规划求解的显著特征!!!2、建⽴递归关系3、计算最优值public static void matrixChain(int n) {for (int i = 1; i <= n; i++) {m[i][i] = 0;}for (int r = 2; r <= n; r++) {//i与j的差值for (int i = 1; i <= n - r + 1; i++) {int j = i + r - 1;m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];s[i][j] = i;for (int k = i + 1; k < j; k++) {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;}}}}}4、构造最优解public static void traceback(int i, int j) {if (i == j) {System.out.printf("A%d", i); // 输出是第⼏个数据return;}System.out.printf("(");traceback(i, s[i][j]);// 递归下⼀个数据System.out.printf(" x ");traceback(s[i][j] + 1, j);System.out.printf(")");}三、总结。

矩阵链乘法(动态规划)

矩阵链乘法(动态规划)

矩阵链乘法(动态规划)
⼀题意描述:
给定由n个要相乘的矩阵构成的序列(链)<A1,A2,A3,····A n>。

由于矩阵满⾜结合律(加括号⽅式表⽰结合⽅式),不同的计算⽅式导致的求出最终计算结果的代价相异,有的花的时间很少,有的⽅式所花时间很多,那么下⾯的任务就是求出算出结果所需要的最少时间及⼀个最优解。

⼆思路分析:
设p(n)表⽰⼀串n个矩阵可能的加全部括号⽅案数。

当n=1时,只有⼀个矩阵,此时p(1)=1。

当n>=2时,⼀个加全部括号的矩阵乘积等于两个加全部括号的⼦矩阵乘积的乘积,⽽且这两个⼦乘积之间的分裂可能发⽣在第k个和第k+1个矩阵之间,其中k=1,2,····,n-1;因此可以求得递归式:
1.找局部最优解:把问题:转化成两个最优⼦问题:及
2.构造递归解:
⾸先定义m[i,j]为解决⼦问题A[i....j]的最⼩计算次数,那么解决整个问题A[1,n]所花的最⼩时间为m[1,n]。

那么递归⽅程可以写成如下形式:
为了跟踪如何构造⼀个最优解我们可以定义s[i,j]为这样的⼀个k值,在该处分裂乘积后可得⼀个最优解。

3.构造函数进⾏求解
输出最优路径的函数⾃⼰编写,经过调⽤数组s[i][j]即可。

矩阵连乘问题的算法

矩阵连乘问题的算法

矩阵连乘问题的算法介绍矩阵连乘问题是一个经典的数学问题,它涉及到如何寻找一组矩阵相乘的最优顺序,使得计算所需的乘法操作总数最小化。

这个问题在计算机科学和算法设计中有着重要的应用。

本文将介绍矩阵连乘问题的算法及其相关概念和应用。

问题描述给定一组矩阵{A1, A2, A3, …, An},其中Ai的维度为pi-1 × pi(1 ≤ i ≤ n),我们希望找到一种矩阵相乘的顺序,使得计算这些矩阵相乘所需的乘法操作总数最小化。

动态规划算法动态规划算法是解决矩阵连乘问题的经典方法。

它通过存储中间结果来避免重复计算,从而提高计算效率。

下面将介绍动态规划算法的具体实现步骤。

定义子问题假设我们要计算矩阵Ai × Ai+1 × … × Aj的最优顺序和乘法操作总数,其中i ≤ j。

确定状态转移方程设m[i][j]表示计算矩阵Ai × Ai+1 × … × Aj的最优顺序和乘法操作总数。

根据定义,我们有以下状态转移方程: - 当i = j时,m[i][j] = 0,因为只有一个矩阵无需进行乘法操作; - 当i < j时,m[i][j] = min{m[i][k] + m[k+1][j] + pi-1 × pk × pj},其中i ≤ k < j。

填表计算最优值根据状态转移方程,我们可以使用动态规划的方法逐步填充表格m。

具体步骤如下:1. 初始化所有m[i][i]为0(0 ≤ i ≤ n); 2. 对于每个子问题(i, j),从i= 1递增到j = n-1,按照递增的长度进行计算: - 对于每个i和j,根据状态转移方程计算m[i][j]; 3. 最终,m[1][n-1]即为所求的计算矩阵Ai × Ai+1× … × An的最优顺序和乘法操作总数。

重构最优解为了得到最优顺序下的具体计算过程,我们可以使用一个辅助表格s来记录最优划分点。

C语言矩阵连乘(动态规划)详解

C语言矩阵连乘(动态规划)详解

C语⾔矩阵连乘(动态规划)详解动态规划法题⽬描述:给定n个矩阵{A1,A2....An},其中Ai与Ai+1是可以相乘的,判断这n个矩阵通过加括号的⽅式相乘,使得相乘的次数最少!以矩阵链ABCD为例按照矩阵链长度递增计算最优值矩阵链长度为1时,分别计算出矩阵链A、B、C、D的最优值矩阵链长度为2时,分别计算出矩阵链AB、BC、CD的最优值矩阵链长度为3时,分别计算出矩阵链ABC、BCD的最优值矩阵链长度为4时,计算出矩阵链ABCD的最优值动归⽅程:分析:k为矩阵链断开的位置d数组存放矩阵链计算的最优值,d[i][j]是以第i个矩阵为⾸,第j个矩阵为尾的矩阵链的最优值,i > 0m数组内存放矩阵链的⾏列信息,m[i-1]和m[i]分别为第i个矩阵的⾏和列(i = 1、2、3...)c语⾔实现代码:#include <stdio.h>#define N 20void MatrixChain(int p[N],int n,int m[N][N],int s[N][N]){int i,j,t,k;int r; //记录相乘的矩阵个数变量for(i=1;i<=n;i++){m[i][i]=0; //当⼀个矩阵相乘时,相乘次数为 0}//矩阵个数从两个开始⼀次递增for(r=2;r<=n;r++){//从某个矩阵开始for(i=1;i<=n-r+1;i++){//到某个矩阵的结束j=i+r-1;//拿到从 i 到 j 矩阵连乘的次数m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];//拿到矩阵连乘断开的位置s[i][j]=i;//寻找加括号不同,矩阵连乘次数的最⼩值,修改 m 数组,和断开的位置 s 数组for(k=i+1;k<j;k++){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;}}}}}int main(void){int n,n1,m1,i,j=2;int p[N]={0}; //存储矩阵的⾏和列数组int m[N][N]={0}; //存储矩阵与矩阵相乘的最⼩次数int s[N][N]={0}; //存储矩阵与矩阵相乘断开的位置printf("请输⼊矩阵个数:\n");scanf("%d",&n);for(i=1;i<=n;i++){printf("请输⼊第%d个矩阵的⾏和列(n1*m1 格式):",i);scanf("%d*%d",&n1,&m1);if(i==1){p[0]=n1;p[1]=m1;}else{p[j++]=m1;}}printf("\n记录矩阵⾏和列:\n");for(i=0;i<=n;i++){printf("%d ",p[i]);}printf("\n");MatrixChain(p,n,m,s);printf("\n矩阵相乘的最⼩次数矩阵为:\n");for(i=1;i<=n;i++){for(j=1;j<=n;j++){printf("%d ",m[i][j]);}printf("\n");}printf("\n矩阵相乘断开的位置矩阵为:\n");for(i=1;i<=n;i++){for(j=1;j<=n;j++){printf("%d ",s[i][j]);}printf("\n");}printf("矩阵最⼩相乘次数为:%d\n",m[1][n]);return 0;}感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

动态规划之矩阵连乘

动态规划之矩阵连乘

动态规划之矩阵连乘【问题描述】给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。

如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

例如,给定三个连乘矩阵{A1,A2,A3}的维数分别是10*100,100*5和5*50,采⽤(A1A2)A3,乘法次数为10*100*5+10*5*50=7500次,⽽采⽤A1(A2A3),乘法次数为100*5*50+10*100*50=75000次乘法,显然,最好的次序是(A1A2)A3,乘法次数为7500次。

分析:矩阵链乘法问题描述:给定由n个矩阵构成的序列{A1,A2,...,An},对乘积A1A2...An,找到最⼩化乘法次数的加括号⽅法。

1)寻找最优⼦结构此问题最难的地⽅在于找到最优⼦结构。

对乘积A1A2...An的任意加括号⽅法都会将序列在某个地⽅分成两部分,也就是最后⼀次乘法计算的地⽅,我们将这个位置记为k,也就是说⾸先计算A1...Ak和Ak+1...An,然后再将这两部分的结果相乘。

最优⼦结构如下:假设A1A2...An的⼀个最优加括号把乘积在Ak和Ak+1间分开,则前缀⼦链A1...Ak的加括号⽅式必定为A1...Ak的⼀个最优加括号,后缀⼦链同理。

⼀开始并不知道k的确切位置,需要遍历所有位置以保证找到合适的k来分割乘积。

2)构造递归解设m[i,j]为矩阵链Ai...Aj的最优解的代价,则3)构建辅助表,解决重叠⼦问题从第⼆步的递归式可以发现解的过程中会有很多重叠⼦问题,可以⽤⼀个nXn维的辅助表m[n][n] s[n][n]分别表⽰最优乘积代价及其分割位置k 。

辅助表s[n][n]可以由2种⽅法构造,⼀种是⾃底向上填表构建,该⽅法要求按照递增的⽅式逐步填写⼦问题的解,也就是先计算长度为2的所有矩阵链的解,然后计算长度3的矩阵链,直到长度n;另⼀种是⾃顶向下填表的备忘录法,该⽅法将表的每个元素初始化为某特殊值(本问题中可以将最优乘积代价设置为⼀极⼤值),以表⽰待计算,在递归的过程中逐个填⼊遇到的⼦问题的解。

矩阵连乘最优结合问题(一)

矩阵连乘最优结合问题(一)

矩阵连乘最优结合问题(一)
矩阵连乘最优结合问题
简介
矩阵连乘最优结合问题是一个经典的动态规划问题,它的目标是找到一种最优的方式来计算一系列矩阵的乘积。

在实际应用中,这个问题往往涉及到优化计算时间和空间的需求。

相关问题及解释
1.矩阵连乘的计算顺序问题:给定一系列矩阵的维度,如何确定它
们的乘积计算顺序,使得总的计算次数最少。

2.最优连乘加括号问题:在确定计算顺序的基础上,如何添加括号
来改变计算的顺序,使得计算的效率更高。

问题1:矩阵连乘的计算顺序问题
•当只有两个矩阵相乘时,它们的乘积计算次数是确定的,并且只有一种可能的计算顺序。

•然而,当矩阵的数量增加时,不同的计算顺序会导致不同的计算次数。

•因此,需要通过动态规划的方法来确定最优的计算顺序。

问题2:最优连乘加括号问题
•在确定了矩阵乘法的计算顺序后,可以通过添加括号来改变计算的顺序。

•这样做的目的是为了减少矩阵乘法的计算次数,从而提高计算效率。

•通过动态规划的方法,可以找到一种最优的添加括号方式。

总结
矩阵连乘最优结合问题是一个经典的动态规划问题,涉及到确定最优的矩阵乘法计算顺序和添加最优的括号方式。

通过动态规划的方法,可以高效地解决这些问题,优化计算时间和空间的利用。

在实际应用中,矩阵连乘最优结合问题具有广泛的应用领域,如计算机图形学、数据分析等。

典型的动态规划举例矩阵连乘问题

典型的动态规划举例矩阵连乘问题

二、 LITTLE SHOP OF FLOWERS
PROBLEM
You want to arrange the window of your flower shop in a most pleasant way. You have F bunches of flowers, each being of a different kind, and at least as many vases ordered in a row. The vases are glued onto the shelf and are numbered consecutively 1 through V, where V is the number of vases, from left to right so that the vase 1 is the leftmost, and the vase V is the rightmost vase. The bunches are moveable and are uniquely identified by integers between 1 and F. These id-numbers have a significance: They determine the required order of appearance of the flower bunches in the row of vases so that the bunch i must be in a vase to the left of the vase containing bunch j whenever i < j. Suppose, for example, you have a bunch of azaleas (id-number=1), a bunch of begonias (id-number=2) and a bunch of carnations (id-number=3). Now, all the bunches must be put into the vases keeping their id-numbers in order. The bunch of azaleas must be in a vase to the left of begonias, and the bunch of begonias must be in a vase to the left of carnations. If there are more vases than bunches of flowers then the excess will be left empty. A vase can hold only one bunch of flowers. Each vase has a distinct characteristic (just like flowers do). Hence, putting a bunch of flowers in a vase results in a certain aesthetic value, expressed by an integer. The aesthetic values are presented in a table as shown below. Leaving a vase empty has an aesthetic value of 0.

动态规划实现矩阵链乘法问题

动态规划实现矩阵链乘法问题

动态规划实现矩阵链乘法问题矩阵链乘法问题( matrix-chain multiplication problem ) (1)问题描述 给定n个矩阵的链<A 1 ,A 2 ,…,A n >,其中i=1,2,…,n,矩阵A i的维数为p i-1 ×p i。

求⼀个完全“括号化⽅案”,使得计算乘积A 1 A 2 …A n 所需的标量乘法次数最⼩ (2)最优括号化⽅案的结构特征 ⽤记号 A i,j表⽰ A i A i+1 …A j通过加括号后得到的⼀个最优计算模式,且恰好在A k与A k+1之间分开。

则“前缀”⼦链A i A i+1 …A k必是⼀个最优的括号化⼦⽅案,记为A i,k;同理“后缀”⼦链A k+1 A k+2 …A j也必是⼀个最优的括号化⼦⽅案,记为A k+1,j。

(3)⼀个递归求解的⽅案 对于矩阵链乘法问题,我们将所有对于1≤i≤j≤n确定A i A i+1 …A j的最⼩代价括号⽅案作为⼦问题。

令m[i,j]表⽰计算矩阵A i,j所需要的标量乘法的次数最⼩值,则最优解就是计算A i...n所需的最低代价就是m[1,n] 递归定义m[i,j]。

①对于i=j的情况下,显然有m=0,不需要做任何标量乘法运算。

所以,对于所有的i=1、2......n,m[i,i] = 0. ②当i < j的情况,就按照最优括号化⽅案的结构特征进⾏计算m[i,j]。

假设最优括号化⽅案的分割点在矩阵A k和A k+1之间,那么m的值就是A i...k和A k+1...j的代价加上两者量程的代价的最⼩值。

即。

该公式的假设是最优分割点是已知的,但是实际上不知道。

然⽽,k只有j-i中情况取值。

由于最优分割点k必定在i~j内取得,只需要检查所有可能的情况,找到最优解即可。

可以得出⼀个递归公式 m只是给出了⼦问题最优解的代价,但是并未给出构造最优解的⾜够信息(即分割点的位置信息)。

所以,在此基础之上,我们使⽤⼀个⼆维数组s[i,j]来保存 A i A i+1 …A j 的分割点位置k。

矩阵链相乘问题的算法是用

矩阵链相乘问题的算法是用

矩阵链相乘问题的算法是用矩阵链相乘问题是一个经典的问题,它的目标是找到一种最优的方式来连乘一系列矩阵,使得计算乘积的总运算量最小。

这个问题在计算机科学和数学领域都具有重要的应用价值。

一种常用的算法解决矩阵链相乘问题是动态规划算法。

动态规划算法是一种通过构建一个最优解的递归结构,并利用子问题的最优解来逐步构建整个问题的最优解的方法。

为了使用动态规划算法解决矩阵链相乘问题,首先需要定义一个特定的问题形式,并设计一个递归解法来解决它。

对于矩阵链相乘问题,可以定义以下形式:假设有n个矩阵 {A1, A2, ..., An},它们的维度分别是 {d0, d1,d2, ..., dn},其中Ai的维度是di-1 x di。

要解决矩阵链相乘问题,需要找到一种最优的括号方案,使得计算乘积的总运算量最小。

可以定义一个函数MCM(i, j)来表示解决从第i个矩阵到第j个矩阵的子问题所需要的最小运算量。

那么,这个问题可以分解为以下两个子问题:1. 计算第i个矩阵到第k个矩阵的子问题所需要的最小运算量:MCM(i, k)2. 计算第k+1个矩阵到第j个矩阵的子问题所需要的最小运算量:MCM(k+1, j)接下来,需要设计一个递归解法来解决这个问题。

可以使用一个循环来遍历可能的k值,从而得到所有可能的组合方式。

对于每个k值,可以计算出相应的运算量,并选择最小的结果。

递归方程可以表示如下:MCM(i, j) = min { MCM(i, k) + MCM(k+1, j) + di-1 * dk * dj } 其中i ≤ k < j,i ≤ 1 < n,MCM(i, i) = 0通过自底向上的方式,可以使用动态规划算法来解决矩阵链相乘问题。

需要构建一个二维数组dp来保存中间计算结果,其中dp[i][j]表示解决从第i个矩阵到第j个矩阵的子问题所需要的最小运算量。

动态规划算法的伪代码如下所示:```for l = 2 to n:for i = 1 to n-l+1:j = i + l - 1dp[i][j] = infinityfor k = i to j-1:q = dp[i][k] + dp[k+1][j] + di-1 * dk * djif q < dp[i][j]:dp[i][j] = q```最后,动态规划算法的最优解可以通过访问dp[1][n]来获取。

动态规划课程设计(矩阵链乘问题)

动态规划课程设计(矩阵链乘问题)

动态规划程序设计实验目的:掌握并实现动态规划算法。

实验内容:对维数为序列(5,10,3,12,5,50,6)的各矩阵。

找出其矩阵链乘的一个最优加全括号。

实验要求:利用动态规划思想写出算法的伪代码和C程序代码(一)算法思想穷举所有的计算次序,且对每一计算次序确定其乘法次数。

由此可找出n个矩阵进行连乘积A1A2…An的最小乘法次数。

将矩阵链乘积简记为A[i:j] ,这里i≤j考察计算A[i:j]的最优计算次序。

设这个计算次序在矩阵Ak和Ak+1之间将矩阵链断开,i≤k<j,则其相应完全加括号方式为计算量:A[i:k]的计算量加上A[k+1:j]的计算量,再加上A[i:k]和A[k+1:j]相乘的计算量设计算A[i:j],1≤i≤j≤n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]当i=j时,A[i:j]=Ai,因此,m[i,i]=0,i=1,2,…,n当i<j时,可以递归地定义m[i,j]为:k位置只有j-i种可能(二)程序代码//动态规划import java.io.*;public class Testsuanfa {public final int len = this.GetN()+1;public int[] A = new int[len];public double[][] M = new double[len][len];public double[][] S = new double[len][len];//取得用户需要规划的矩阵连乘的个数。

public int GetN(){int dvalue = 0;String value;System.out.println("请输入连乘矩阵个数:");BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));try {value = bfr.readLine();dvalue =Integer.parseInt(value);//捕捉输入异常} catch (IOException e) {System.out.println("输入出错了,请重新输入:");System.exit(0);}catch (NumberFormatException e2) {System.out.println("请输入正确的数字!!");System.exit(0);}return dvalue;}//输入矩阵的序列public int GetA(){int dvalue = 0;String value;System.out.println("请输入分别矩阵维数序列:");BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));try {value = bfr.readLine();dvalue =Integer.parseInt(value);//捕捉输入异常} catch (IOException e) {System.out.println("输入出错了,请重新输入:");System.exit(0);}catch (NumberFormatException e2) {System.out.println("请输入正确的数字!!");System.exit(0);}return dvalue;}public void f(){//调用GetA方法,拿到每个序列值for(int i=0;i<len;i++){A[i] = this.GetA();}for(int i=0;i<len;i++){M[i][i] = 0;}//依次从长度为2到len,求解每一个长度的最有加全括号。

动态规划-矩阵链相乘

动态规划-矩阵链相乘

感谢您的观看
THANKS
应用场景
稀疏矩阵的矩阵链相乘问题在科学计算、工程仿真等领域有广泛的应用。例如,在计算流体动力学中, 需要将多个稀疏矩阵相乘来模拟流体流动;在电磁场分析中,需要将多个稀疏矩阵相乘来计算电磁场的 分布。
矩阵链相乘问题的近似算法
定义
求解方法
矩阵链相乘问题的近似算法是指在保 证计算精度的情况下,通过牺牲一定 程度的计算量来加速计算过程的方法 。
标量乘法次数最少。
02
矩阵链相乘的动态规划算法
动态规划的基本概念
最优化原理
将原问题分解为若干个子问题 ,并从最优子问题的解逐步构
造出原问题的最优解。
状态
描述问题的中间状态,通常用 变量表示。
决策
在状态之间进行选择,通常用 函数表示。
状态转移方程
描述状态之间的依赖关系。
矩阵链相乘问题的动态规划解决方案
矩阵链相乘问题的最优解
最优解的求解过程
确定矩阵链
首先需要确定要相乘的矩阵链,即确定矩阵的顺 序。
构建状态转移方程
根据确定的矩阵链,构建状态转移方程,描述子 问题的最优解与原问题的最优解之间的关系。
求解状态转移方程
通过迭代求解状态转移方程,得到每个子问题的 最优解,进而得到原问题的最优解。
最优解的验证
验证解的有效性
通过检查每个子问题的最优解是否满 足状态转移方程,验证求解过程的有 效性。
验证解的正确性
通过将最优解代入原问题,验证其是 否能够得到正确的结果。
最优解的应用场景
矩阵运算优化
在科学计算、机器学习等领域中,经常需要进行大规模的矩 阵运算,矩阵链相乘问题的最优解可以用于优化这些运算过 程。

0010算法笔记——【动态规划】矩阵连乘问题

0010算法笔记——【动态规划】矩阵连乘问题

问题描述:给定n个矩阵:A1,A2,...,A n,其中A i与A i+1是可乘的,i=1,2...,n-1。

确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。

问题解析:由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。

这种计算次序可以用加括号的方式来确定。

若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。

完全加括号的矩阵连乘积可递归地定义为:(1)单个矩阵是完全加括号的;(2)矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC)例如,矩阵连乘积A1A2A3A4有5种不同的完全加括号的方式:(A1(A2(A3A4))),(A1((A2A3)A4)),((A1A2)(A3A4)),((A1(A2A3))A4),(((A1A2)A3)A4)。

每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。

看下面一个例子,计算三个矩阵连乘{A1,A2,A3};维数分别为10*100 , 100*5 , 5*50 按此顺序计算需要的次数((A1*A2)*A3):10X100X5+10X5X50=7500次,按此顺序计算需要的次数(A1*(A2*A3)):10*5*50+10*100*50=75000次所以问题是:如何确定运算顺序,可以使计算量达到最小化。

算法思路:例:设要计算矩阵连乘乘积A1A2A3A4A5A6,其中各矩阵的维数分别是:A1:30*35; A2:35*15; A3:15*5; A4:5*10; A5:10*20; A6:20*25递推关系:设计算A[i:j],1≤i≤j≤n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]。

实现矩阵连乘的动态规划算法

实现矩阵连乘的动态规划算法

实现矩阵连乘的动态规划算法1.计算连个矩阵乘积的标准算法://标准算法void MatrixMultiply(int a[][MAXN], int b[][MAXN], int p, int q, int r){int sum[MAXN][MAXN];memset(sum, 0, sizeof(sum));int i, j, k;//遍历矩阵a的⾏for (k = 0; k < p; k++){//遍历矩阵b的列for (j = 0; j < r; j++){//对应位置相乘for (i = 0; i < q; i++){sum[k][j] += a[k][i] * b[i][j];}}}}所以A、B两个矩阵相乘的计算量为p*q*r。

2. 计算连个矩阵乘积的动态规划算法:#include<stdio.h>#include<stdlib.h>#include<Windows.h>#define MAX 100int matrix_chain(int *p, int n, int **m, int **s){//a[][]最⼩乘次数//s[][]最⼩乘数时的断开点int i,j,r,k;for (i = 0; i < n; i++) //单⼀矩阵的最⼩乘次都置为0{m[i][i] = 0;}for (r = 2; r <= n; r++) //r为连乘矩阵的个数{for (i = 0; i <= n-r; i++) //i表⽰连乘矩阵中的第⼀个{j = i + r -1; //j表⽰连乘矩阵中的最后⼀个m[i][j] = 99999;for (k = i; k <= j-1; k++) //在第⼀个与最后⼀个之间寻找最合适的断开点,注意,这是从i开始,即要先计算两个单独矩阵相乘的乘次{int tmp = m[i][k] + m[k+1][j] + p[i]*p[k+1]*p[j+1];if (tmp < m[i][j]){m[i][j] = tmp;s[i][j] = k;}}}}return m[0][n-1];}void print_chain(int i, int j, char **a,int **s){ //递归的⽅式来把最⼩乘数的表达式输出if (i == j){printf("%s",a[i]);}else{printf("(");print_chain(i,s[i][j],a,s);print_chain(s[i][j]+1,j,a,s);printf(")");}}int main(){//min_part[i][j]存储的是i+1到j+1的最⼩乘次,因为是从0开始//min_point[i][j]存储的是i+1到j+1之间最⼩乘次时的分割点int *p, **min_part, **min_point;char **a;int n = 6,i;int ret;p = (int *)malloc((n+1)*sizeof(int));a = (char **)malloc(n*sizeof(char*));min_part = (int **)malloc(n*sizeof(int *)); min_point = (int **)malloc(n*sizeof(int *));for (i = 0; i < n; i++){min_part[i] = (int *)malloc(n*sizeof(int)); min_point[i] = (int *)malloc(n*sizeof(int));a[i] = (char *)malloc(n*sizeof(char));}p[0] = 30; //第⼀个矩阵的⾏数p[1] = 35; //第⼆个矩阵的⾏数p[2] = 15; //……p[3] = 5; //……p[4] = 10; //……p[5] = 20; //第六个矩阵的⾏数p[6] = 25; //第六个矩阵的列数a[0] = "A1";a[1] = "A2";a[2] = "A3";a[3] = "A4";a[4] = "A5";a[5] = "A6";ret = matrix_chain(p,n,min_part,min_point); printf("Minest times:%d.\n",ret);print_chain(0,n-1,a,min_point);printf("\n");free(p);free(min_part);free(min_point);free(a);system("pause");return 0;}3.递归加括号的过程的运算量://加括号的过程是递归的。

矩阵连乘问题(内附动态规划算法代码)

矩阵连乘问题(内附动态规划算法代码)

矩阵连乘问题(内附动态规划算法代码)矩阵连乘问题若矩阵A是⼀个p*q的矩阵,B是⼀个q*r的矩阵,则C=AB,是⼀个p*r的矩阵,需进⾏pqr次数乘计算。

存在{A1,A2,A3}三个矩阵,维数分别为100*5,5*50,50*10。

若直接相乘,A1*A2*A3,则需要进⾏n=100*5*50+100*50*10=25000+50000=75000次数乘计算。

如果我们调整运算顺序,A1*(A2*A3),则需要进⾏n=5*50*10+100*5*10=2500+5000=7500次数乘计算。

由此可见,当进⾏矩阵连乘运算时,加括号的⽅式,即计算次序对计算量有很⼤的影响。

代码展⽰:1 #include<iostream>23using namespace std;4/*5⾃底向上的推出矩阵连乘的最优解6先从两个矩阵相乘开始,⽽后三个矩阵相乘,四个......直到推出⽬标长度的最优解,即假设⼀个矩阵链,初始长度为2,算出所有相邻矩阵相乘的计算次数,⽽后使其长度为3...4...直到⽬标长度 7状态转移⽅程:8 m[i][j]=min {m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]} i<=k<j i<j9 m[i][j]=0 i==j;10*/11#define LEN 5 //矩阵个数12//矩阵连乘函数,找到最优解13void MatrixChain(int *p, int m[][LEN + 1], int s[][LEN + 1]) {14for (int i = 0; i < LEN + 1; i++) m[i][i] = 0; //初始化,对⾓线元素置零,即当矩阵链长度为1时(只有⼀个矩阵)不⽤乘,为零15for (int r = 2; r <= LEN; r++) { //r表⽰矩阵链的长度,从2开始,两个矩阵相乘,⽽后3...4...5...16for (int i = 1; i <= LEN - r + 1; i++) { //i是矩阵链的⾸个矩阵,⼩于矩阵个数减矩阵链长度加⼀17int j = i + r - 1; //j是矩阵链的最后⼀个元素18 m[i][j] = m[i][i] + m[i + 1][j] + p[i - 1] * p[i] * p[j]; //m[i][j]是⼦结构,从最左边开始推19 s[i][j] = i; //标记断开的位置20for (int k = i + 1; k < j; k++) { //k是i和j直接的断开点,是在i和j之间的⼦结构,通过k的循环找到最优的解21int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; //状态转移⽅程22if (t < m[i][j]) {23 m[i][j] = t; //更新最优解24 s[i][j] = k; //更新断开点25 }26 }27 }28 }29 }3031//回溯函数,根据s[i][j]数组标记的位置,回溯找到断开的位置32void Traceback(int i, int j, int s[][LEN + 1]) {33if (i == j) { //当i与j相等说明回溯到该矩阵的位置了34 cout << "A" << i;35 }36else {37 cout << "(";38 Traceback(i, s[i][j], s); //从尾往头回溯39 Traceback(s[i][j] + 1, j, s); //从断点往后回溯40 cout << ")";41 }42 }43//输出函数44void output(int t[][LEN + 1]) {45for (int i = 1; i <= LEN; i++) {46for (int j = 1; j <= LEN; j++) {47 cout << "" << t[i][j] << "";48 }49 cout << endl;50 }51 }52int main(void) {53int p[LEN + 1] = { 6,8,9,3,4,10 }; //矩阵的维度分别是2*3,3*4,4*5,5*6,6*7,LEN+1个数表⽰LEN个矩阵54int m[LEN + 1][LEN + 1] = { 0 }; //记录最优⼦结构的⼆维数组55int s[LEN + 1][LEN + 1] = { 0 }; //记录最优解对应的括号的位置5657 MatrixChain(p, m, s);5859 cout << endl;60 output(m);61 cout << endl;62 output(s);63 cout << endl;64 cout << "outcome:" <<endl;65 Traceback(1, LEN, s);66 cout << endl;6768return0;69 }运⾏结果:与备忘录⽅法的区别:我们使⽤的动态规划⽅法中其实融⼊了备忘录的⼀些东西,我们的m和s数组都是⽤来记录的,所以备忘录⽅法与我们使⽤的⽅法类似,不同在于,我们是⾃底向上的,⽽备忘录⽅法是⾃顶向下的进⾏。

矩阵链乘法问题

矩阵链乘法问题

矩阵链乘法问题什么是矩阵链乘法问题?矩阵链乘法问题是计算一系列矩阵相乘的最优方式的问题。

给定n个矩阵,它们的维度分别为d0×d1,d1×d2,...,dn-1 ×dn。

假设这些矩阵按照顺序相乘,即(A1A2)(A3A4)...(An-1An),那么计算这个式子所需的标量乘法次数就取决于每个括号内部的矩阵相乘顺序。

因此,我们需要找到一种最优的括号方案来使得标量乘法次数最小。

如何解决矩阵链乘法问题?动态规划是解决矩阵链乘法问题的经典方法。

该方法将原始问题分解为子问题,并使用已知子问题的解来求解原始问题。

具体地说,在矩阵链乘法中,我们定义一个二维数组m[i][j]表示从第i个到第j个矩阵所需的最小标量乘法次数。

同时,我们还定义一个二维数组s[i][j]表示从第i个到第j个矩阵中最优括号方案中第一个括号所包含的最后一个位置k。

根据上述定义,我们可以得出以下递推式:m[i][j]=min{m[i][k]+m[k+1][j]+di-1×dk×dj}(i≤k<j)s[i][j]=argmin{m[i][k]+m[k+1][j]+di-1×dk×dj}(i≤k<j)其中,di-1 ×dk×dj表示第i个到第j个矩阵相乘的标量乘法次数。

因此,递推式的含义是:从第i个到第j个矩阵所需的最小标量乘法次数等于将这些矩阵分成两部分的最小标量乘法次数加上这两部分相乘的标量乘法次数。

同时,我们需要遍历所有可能的括号方案来找到最优方案中第一个括号所包含的最后一个位置k。

如何实现动态规划算法?动态规划算法可以使用自底向上的方式实现。

具体地说,我们从长度为2开始逐步增加到长度为n,依次计算出每个子问题的解。

在计算每个子问题时,我们需要遍历所有可能的括号方案,并选择其中标量乘法次数最小的方案作为该子问题的解。

以下是动态规划算法实现的伪代码:MatrixChainOrder(p,n,m,s)for i=1 to nm[i][i]=0for l=2 to nfor i=1 to n-l+1j=i+l-1m[i][j]=∞for k=i to j-1q=m[i][k]+m[k+1][j]+p[i-1]×p[k]×p[j]if q<m[i][j]m[i][j]=qs[i][j]=kreturn m and s其中,p是一个长度为n+1的数组,表示每个矩阵的维度。

矩阵连乘最佳加括号方式动态规划算法

矩阵连乘最佳加括号方式动态规划算法

矩阵连乘最佳加括号方式-动态规划算法一、问题描述给定n个矩阵{A1,A2,…,A n},其中A i与A i+1是可乘的,i=1,2,…,n-1。

要算出这n个矩阵的连乘积A1A2…A n。

由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。

这种计算次序可以用加括号的方式来确定。

若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。

完全加括号的矩阵连乘积可递归地定义为:(1)单个矩阵是完全加括号的;(2)矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C 的乘积并加括号,即A=(BC)。

例如,矩阵连乘积A1A2A3A4有5种不同的完全加括号的方式:(A1(A2(A3A4))),(A1((A2A3)A4)),((A1A2)(A3A4)),((A1(A2A3))A4),(((A1A2)A3)A4)。

每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。

若A是一个p×q矩阵,B是一个q×r矩阵,则计算其乘积C=AB的标准算法中,需要进行pqr次数乘。

为了说明在计算矩阵连乘积时,加括号方式对整个计算量的影响,先考察3个矩阵{A1,A2,A3}连乘的情况。

设这三个矩阵的维数分别为10×100,100×5,5×50。

加括号的方式只有两种:((A1A2)A3),(A1(A2A3)),第一种方式需要的数乘次数为10×100×5+10×5×50=7500,第二种方式需要的数乘次数为100×5×50+10×100×50=75000。

第二种加括号方式的计算量时第一种方式计算量的10倍。

由此可见,在计算矩阵连乘积时,加括号方式,即计算次序对计算量有很大的影响。

[说明]计算矩阵连乘积

[说明]计算矩阵连乘积

计算矩阵连乘积问题描述在科学计算中经常要计算矩阵的乘积。

矩阵A和B可乘的条件是矩阵A的列数等于矩阵B的行数。

若A是一个p×q的矩阵,B是一个q×r的矩阵,则其乘积C=AB是一个p ×r的矩阵。

其标准计算公式为:由该公式知计算C=AB总共需要pqr次的数乘。

现在的问题是,给定n个矩阵{A1,A2,…,A n}。

其中A i与A i+1是可乘的,i=1,2,…,n-1。

要求计算出这n个矩阵的连乘积A1A2…A n。

由于矩阵乘法满足结合律,故连乘积的计算可以有许多不同的计算次序。

这种计算次序可以用加括号的方式来确定。

若一个矩阵连乘积的计算次序已完全确定,也就是说该连乘积已完全加括号,则我们可以通过反复调用两个矩阵相乘的标准算法计算出矩阵连乘积。

完全加括号的矩阵连乘积可递归地定义为:1. 单个矩阵是完全加括号的;2. 若矩阵连乘积A是完全加括号的,则A可表示为两个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC)。

例如,矩阵连乘积A1A2A3 A4可以有以下5种不同的完全加括号方式:(A1(A2(A3A4))),(A1((A2A3)A4)),((A1A2)(A3A4)),((A1(A2A3))A4),(((A1A2)A3)A4)。

每一种完全加括号方式对应于一种矩阵连乘积的计算次序,而这种计算次序与计算矩阵连乘积的计算量有着密切的关系。

为了说明在计算矩阵连乘积时加括号方式对整个计算量的影响,我们来看一个计算3个矩阵{A1,A2,A3}的连乘积的例子。

设这3个矩阵的维数分别为10×100,100×5和5×50。

若按第一种加括号方式((A1A2)A3)来计算,总共需要10×100×5+10×5×50=7500次的数乘。

若按第二种加括号方式(A1(A2A3))来计算,则需要的数乘次数为100×5×50+10×100×50=75000。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

矩阵连乘最佳加括号方式-动态规划算法
一、问题描述
给定n个矩阵{A1,A2,…,A n},其中A i与A i+1是可乘的,i=1,2,…,n-1。

要算出这n个矩阵的连乘积A1A2…A n。

由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。

这种计算次序可以用加括号的方式来确定。

若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。

完全加括号的矩阵连乘积可递归地定义为:
(1)单个矩阵是完全加括号的;
(2)矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C 的乘积并加括号,即A=(BC)。

例如,矩阵连乘积A1A2A3A4有5种不同的完全加括号的方式:(A1(A2(A3A4))),(A1((A2A3)A4)),((A1A2)(A3A4)),((A1(A2A3))A4),(((A1A2)A3)A4)。

每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。

若A是一个p×q矩阵,B是一个q×r矩阵,则计算其乘积C=AB的标准算法中,需要进行pqr次数乘。

为了说明在计算矩阵连乘积时,加括号方式对整个计算量的影响,先考察3个矩阵
{A1,A2,A3}连乘的情况。

设这三个矩阵的维数分别为10×100,100×5,5×50。

加括号的方式只有两种:((A1A2)A3),(A1(A2A3)),第一种方式需要的数乘次数为10×100×5+10×5×50=7500,第二种方式需要的数乘次数为100×5×50+10×100×50=75000。

第二种加括号方式的计算量时第一种方式计算量的10倍。

由此可见,在计算矩阵连乘积时,加括号方式,即计算次序对计算量有很大的影响。

于是,自然提出矩阵连乘积的最优计算次序问题,即对于给定的相继n个矩阵{A1,A2,…,A n}(其中矩阵A i的维数为p i-1×p i,i=1,2,…,n),如何确定计算矩阵连乘积A1A2…A n的计算次序(完全加括号方式),使得依此次序计算矩阵连乘积需要的数乘次数最少。

穷举搜索法的计算量太大,它不是一个有效的算法,本实验采用动态规划算法解矩阵连乘积的最优计算次序问题。

二、算法思路
动态规划算法的基本思想是将待求解问题分成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。

与分治法不同的是,动态规划法经分解得到的子问题往往不是相互独立的,前一子问题的解为后一子问题的解提供有用的信息,可以用一个表来记录所有已解决的子问题的答案,不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。

本实验的算法思路是:
1、计算最优值算法MatrixChain():建立两张表(即程序中的**m和**s,利用二维指针存放),一张表存储矩阵相乘的最小运算量,主对角线上的值为0,依次求2个矩阵、3个矩阵…、直到n个矩阵相乘的最小运算量,其中每次矩阵相乘的最小运算量都在上一次矩阵相乘的最小运算量的基础上求得,最后一次求得的值即为n个矩阵相乘的最小运算量;另一张表存储最优断开位置。

2、输出矩阵结合方式算法Traceback():矩阵结合即是给矩阵加括号,打印出矩阵结合方式,由递归过程Traceback()完成。

分三种情况:
(1)只有一个矩阵,则只需打印出A1;
(2)有两个矩阵,则需打印出(A1A2);
(3)对于矩阵数目大于2,则应该调用递归过程Traceback()两次,构造出最优加括号方式。

三、实验源程序
建立一个矩阵的类Matrix。

Matrix.h代码
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
public:
Matrix(); //构造函数
~Matrix(); //析构函数
bool Run(); //运行接口函数
private:
int W; //记录矩阵的个数
int **m; //存放最优值,即最小运算量
int **s; //断开位置
int *p; //存放
bool Input(); //处理输入
bool MatrixChain();//计算最优值算法
void Traceback(int i,int j,int **s); //输出矩阵加括号的方式};
#endif
Matrix.cpp代码
#define N 50
#include <iostream.h>
#include <stdlib.h>
#include "Matrix.h"
//构造函数,作变量初始化工作,为指针分配内存空间
Matrix::Matrix()
{
W=0;
m = new int*[N];
s = new int*[N];
for(int i=0; i<N ; i++)
{
m[i] = new int[N];
s[i] = new int[N];
}
p = new int[N];
}
//析构函数,释放内存
Matrix::~Matrix()
{
for(int i=0; i<N ; i++)
{
delete []m[i];
delete []s[i];
}
delete []m;
delete []s;
delete []p;
}
//处理键盘输入
bool Matrix::Input()
{
int w;
cout<<"矩阵个数:";
cin>>w;
W = w;
cout<<"输入矩阵A1维数"<<":";
cin>>p[0]>>p[1];
for(int i=2 ; i<=W ; i++)
{
int m = p[i-1];
cout<<"输入矩阵A"<<i<<"维数:";
cin>>p[i-1]>>p[i];
if(p[i-1] != m)
{
cout<<endl<<"维数不对,矩阵不可乘!"<<endl;
exit(1);
}
//cout<<endl;
}
if(p!=NULL)
return true;
else
return false;
}
//计算最优值算法
bool Matrix::MatrixChain()
{
if(NULL == p)
return false;
for(int i=1;i<=W;i++)
m[i][i]=0;
for(int r=2;r<=W;r++)
for(int i=1;i<=W-r+1;i++)
{
int j=i+r-1;
m[i][j] = m[i+1][j] + p[i-1]*p[i]*p[j];
s[i][j] = i;
for(int k=i+1;k<j;k++)
{
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;
}
}
}
return true;
}
//输出矩阵结合方式,加括号
void Matrix::T raceback(int i,int j,int **s)
{
if(i == j)
{
cout<<"A"<<i;
}
else if(i+1 == j)
{
cout<<"(A"<<i<<"A"<<j<<")";
}
else
{
cout<<"(";
T raceback(i,s[i][j],s);
T raceback(s[i][j]+1,j,s);
cout<<")";
}
}
bool Matrix::Run()
{
if(Matrix::Input())
{
if(Matrix::MatrixChain())
{
Matrix::T raceback(1,W,s);
cout<<endl;
return true;
}
else
return false;
}
else
return false; }
main.cpp代码
#include "Matrix.h"
void main()
{
Matrix m;
m.Run();
}。

相关文档
最新文档