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

合集下载

矩阵连乘问题的算法

矩阵连乘问题的算法

矩阵连乘问题的算法
一、矩阵连乘问题
矩阵连乘问题是指在矩阵计算中,给定n个矩阵,求这n个矩阵的连乘积的最优解问题。

矩阵连乘问题既可以用于组合优化,也可以用于信息处理系统中查找最优路径的搜索算法。

它是最基本的组合优化问题。

二、矩阵连乘问题的算法
1. 动态规划法:动态规划法是求解矩阵连乘问题的常用算法。

它采用递归方法,将原问题分解为若干个子问题,然后求出各子问题的最优解,最后组合出原问题的最优解。

2. 贪心算法:贪心算法是一种经典的最优化算法,也可以用于求解矩阵连乘问题,即通过某种启发式规则,在每一步中都使最优决策,最终得到最优解。

3. 分支定界法:分支定界法是一种由搜索算法和界定法相结合而成的最优化算法,也可以用于求解矩阵连乘问题。

该算法按照树状的层次结构,向下搜索一个在每一步骤都使得当前最优的路径,然后上溯形成最优解。

4. 模拟退火算法:模拟退火算法是一种搜索算法,它可以用于求解矩阵连乘问题。

它采用一种模拟物理过程的原理,通过不断地改变解的状态,以求出相对最优解。

- 1 -。

矩阵连乘最优结合问题

矩阵连乘最优结合问题

矩阵连乘最优结合问题摘要:一、问题背景及意义二、矩阵连乘最优结合问题的定义和描述三、矩阵连乘最优结合问题的求解方法1.暴力枚举法2.贪心算法3.动态规划四、算法分析和比较五、矩阵连乘最优结合问题在实际应用中的案例六、总结与展望正文:一、问题背景及意义在计算机科学和运筹学领域,矩阵连乘最优结合问题(Matrix Multiplication Optimal Matching Problem,简称MMOP)引起了广泛关注。

该问题源于矩阵快速幂运算,旨在寻找一种高效的矩阵乘法结合方式,以降低时间复杂度。

矩阵连乘最优结合问题在图像处理、信号处理、矩阵快速幂等领域具有重要的实际意义。

二、矩阵连乘最优结合问题的定义和描述给定两个矩阵A和B,矩阵连乘最优结合问题就是在一个有向图G(A,B)中,寻找一条从顶点A到顶点B的路径,使得路径上的矩阵乘法次数最少。

路径上的矩阵乘法次数等于路径长度乘以矩阵A和B的规模。

求解该问题,就是寻找一个最优的路径,使得乘法次数最小。

三、矩阵连乘最优结合问题的求解方法1.暴力枚举法:对于每条从顶点A到顶点B的路径,计算路径长度乘以矩阵A和B的规模,然后排序。

选择最小乘法次数的路径作为最优路径。

该方法时间复杂度为O(nm^2),其中n和m分别为矩阵A和B的行数和列数。

2.贪心算法:在每一步中,选择当前最优的顶点作为下一个顶点,直到到达目标顶点B。

贪心算法能够在一定程度上找到最优解,但不一定能得到全局最优解。

3.动态规划:将矩阵连乘最优结合问题转化为一个最短路径问题。

定义一个矩阵D,其中D[i][j]表示从顶点i到顶点j的最小乘法次数。

从顶点A开始,依次计算每个顶点的前驱顶点,直到到达顶点B。

最后得到的路径即为最优路径。

动态规划方法的时间复杂度为O(nm^2)。

四、算法分析和比较暴力枚举法虽然简单易懂,但时间复杂度较高,不适合大规模数据的计算。

贪心算法在某些情况下可以找到最优解,但不是全局最优解。

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

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

动态规划法解矩阵连乘问题实验内容给定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]即可。

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

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

矩阵连乘最佳加括号方式-动态规划算法一、问题描述给定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,…,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:最优连乘加括号问题
•在确定了矩阵乘法的计算顺序后,可以通过添加括号来改变计算的顺序。

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

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

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

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

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

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

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

矩阵连乘问题(内附动态规划算法代码)矩阵连乘问题若矩阵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数组都是⽤来记录的,所以备忘录⽅法与我们使⽤的⽅法类似,不同在于,我们是⾃底向上的,⽽备忘录⽅法是⾃顶向下的进⾏。

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

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

动态规划实现矩阵链乘法问题矩阵链乘法问题( 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个矩阵,它们的维度分别为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的数组,表示每个矩阵的维度。

[说明]计算矩阵连乘积

[说明]计算矩阵连乘积

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

矩阵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。

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

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

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

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

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

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

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

对于矩阵链相乘问题,可以定义以下形式:假设有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,求解每一个长度的最有加全括号。

矩阵连乘问题动态规划[1]

矩阵连乘问题动态规划[1]

矩阵连乘问题【问题】:矩阵链乘问题:给定n个矩阵{A1,A2,...,An},其中Ai与Ai+1是可乘的,i=1,2...,n-1。

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

【解题】:这里我采用的是动态划分算法:设计动态规划算法的步骤。

(1)找出最优解的性质,并刻划其结构特征。

(2)递归地定义最优值。

(3)以自底向上的方式计算出最优值。

(4)根据计算最优值时得到的信息,构造最优解(由子结构的最优解得到原先大问题的最优解)。

【解题关键】:将一系列相乘的矩阵(Ai....Aj)划分为两部分;即(AiA i+1...A k)(A k+1A k+2....Aj),k的位置要保证左边括号和右边括号相乘的消耗最小。

【思路】:这里我采用两种方法来实现:(1)用三重for循环来实现:根据主对角线的方向及其右边与之平行的对角线方向,由上至下,从左到右分别求出C[i][j]的值,后面要求的值都可以根据前面所求的的值来求。

C[i][j]代表矩阵链Ai..Aj相乘的最小消耗。

其中:c[i][i]=0,i=1,2,....n求解的顺序如下:C[1][2],C[2][3],C[2][3],...,C[N-1][N],C[1][3],C[2][4]....C[N-2][N]..........C[N][N]最后得到的C[N][N]的值就是我们所求的。

(2)备忘录方法(即递归算法):将整个矩阵链分成两部分,然后在分别对两边的子矩阵链递归调用算法。

【程序代码】:两种方法都在其中:#include<iostream.h>#include<stdlib.h>#include<limits.h>#include<time.h>#define MAX_VALUE 100#define N 201 //连乘矩阵的个数(n-1)#define random() rand()%MAX_VALUE //控制矩阵的行和列的大小int c[N][N], s[N][N], p[N];int matrixchain(int n) //3个for循环实现{ for(int k=1;k<=n;k++)c[k][k]=0;for(int d=1;d<n;d++)for(int i=1;i<=n-d;i++){ int j=i+d;c[i][j]=INT_MAX;for(int m=i;m<j;m++){ int t=c[i][m]+c[m+1][j]+p[i-1]*p[m]*p[j];if(t<c[i][j]){c[i][j]=t;s[i][j]=m;}}}return c[1][n];}void Print(int s[][N],int i,int j) // 输出矩阵连乘积的计算次序{ if(i==j)cout<<"A"<<i;else{cout<<"(";Print(s,i,s[i][j]); // 左半部子矩阵连乘Print(s,s[i][j]+1,j); //左半部子矩阵连乘cout<<")";}}int lookupchain(int i,int j) //备忘录方法{if(c[i][j]>0)return c[i][j];if(i==j)return 0;int u=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<u){u=t;s[i][j]=k;}}c[i][j]=u;return u;}void main(){srand((int)time(NULL));for(int i=0;i<N;i++) // 随机生成数组p[],各个元素的值的范围:1~MAX_VALUE p[i]=random()+1;clock_t start,end;double elapsed;start=clock();//cout<<"Count: "<<matrixchain(N-1)<<endl; //3重for循环实现cout<<"Count: "<<lookupchain(1,N-1)<<endl; //备忘录方法end=clock();elapsed=((double)(end-start));///CLOCKS_PER_SEC;cout<<"Time: "<<elapsed<<endl;Print(s,1,N-1); //输出矩阵连乘积的计算次序cout<<endl;}【总结】:两种算法的时间复杂度均为o(n3),,随着数据量的增多,备忘录方法消耗的时间越长;我觉得是由于递归算法,随着数据量增大,调用函数的次数也增大,语句被执行的时间也越多,因此调用函数消耗的时间也增多。

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.递归加括号的过程的运算量://加括号的过程是递归的。

  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::Traceback(int i,int j,int **s)
{
if(i == j)
{
cout<<"A"<<i;
}
else if(i+1 == j)
{
cout<<"(A"<<i<<"A"<<j<<")";
}
else
{
cout<<"(";
Traceback(i,s[i][j],s);
Traceback(s[i][j]+1,j,s);
cout<<")";
}
}
bool Matrix::Run()
{
if(Matrix::Input())
{
if(Matrix::MatrixChain())
{
Matrix::Traceback(1,W,s);
cout<<endl;
return true;
}
else
return false;
}
else
return false; }
main.cpp代码
#include "Matrix.h"
void main()
{
Matrix m;
m.Run();
}。

相关文档
最新文档