矩阵相乘问题:
完全加括号的矩阵连乘积可递归地定义为:
(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次
所以问题是:如何确定运算顺序,可以使计算量达到最小化。
int p[L]={30,35,15,5,10,20,25};
记录上面的a1,a2,a3....的值//p用来记录矩阵的行列,main函数中有说明 5 //m[i][j]用来记录第i个矩阵至第j个矩阵的最优解 6 //s[][]用来记录从哪里断开的才可得到该最优解 7 int p[MAX+1],m[MAX][MAX],s[MAX][MAX]; 8 int n;//矩阵个数 9 10 void matrixChain(){ 11 for(int i=1;i<=n;i++)m[i][i]=0; 12 13 for(int r=2;r<=n;r++)//对角线循环,在这里面用来控制M[i:j]的长度 14 for(int i=1;i<=n-r+1;i++){//行循环 15 int j = r+i-1;//列的控制,是链的最后一个长度值
16 //找m[i][j]的最小值,先初始化一下,令k=i 17 m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j]; 18 s[i][j]=i; 19 //k从i+1到j-1循环找m[i][j]的最小值 20 for(int k = i+1;k<j;k++){ 21 int temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]; 22 if(temp<m[i][j]){ 23 m[i][j]=temp; 24 //s[][]用来记录在子序列i-j段中,在k位置处 25 //断开能得到最优解 26 s[i][j]=k; 27 } 28 } 29 } 30 } 31
举例:
当R=2时,先迭代计算出:
m[1:2]=m[1:1]+m[2:2}+p[0]*p[1]*p[2];
m[2:3]=m[2:2]+m[3:3]+p[1]*p[2]*p[3];
m[3:4]=m[3:3]+m[4][4]+p[2]*p[3]*p[4];
m[4:5]=m[4:4]+m[5][5]+p[3]*p[4]*p[5];
m[5:6]=m[5][5]+m[6][6]+p[4]*p[5]*p[6]的值;
当R=3时,迭代计算出:
m[1:3]=min(m[1:1]+m[2:3]+p[0]*p[1]*p[3],m[1:2]+m[3:3]+p[0]*p[2]*p[3]);
m[2:4]=min(m[2:2]+m[3:4]+p[1]*p[2]*p[4],m[2:3]+m[4:4]+p[1]*p[3]*p[4]);
......
m[4:6]=min(m[4:4]+m[5:6]+p[3]*p[4]*p[6],m[4:5]+m[6:6]+p[3]*p[5]*p[6]);
......
例如,在计算m[2][5]时,依递归式有
所以m[2][5] = 7125,且k=3,因此,s[2][5]=3。
通过这些可以得到一个最优值:
但是怎么通过s[i][j]的到最优值呢
参考:http://blog.csdn.net/liufeng_king/article/details/8497607
参考:http://www.cnblogs.com/liushang0419/archive/2011/04/27/2030970.html