算法复习周------“动态规划之‘矩阵连乘’”

问题描述:  设有三个矩阵 A[a][b]、B[b][c]、C[c][d]。这个时候我们将ABC排列并相乘:A*B*C,这个时候我们会发现我们有两种不同的矩阵乘法次序——(A*B)*C与A*(B*C)。这个时候我们若要求解矩阵连乘的数乘次序——我们可以分为两个情况

①(A*B)*C——这个时候A*B的连乘次序为a*b*c(因为A的矩阵是a行b列,B的矩阵是b行c列,所以这两个矩阵每一次行列相乘都进行b次乘积,并且他们共进行a*c次乘法运算)当A*B后得到的新矩阵为A'[a][c]此时要计算A'与C的次序,同理为a*c*d。这个时候我们就得到乘积次序的和为a*b*c+a*c*d

②A*(B*C)——这个时候我们先求B*C,由①中结论我们知道B*C为b*c*d,得B'[b][d],此时A*B'为a*b*d,得乘积和为b*c*d+a*b*d

由次我们知道同一个矩阵相乘括号次序不同得到的结果不同。为了更好理解下面我给出一道例题:

  

                        

 算法描述:在这个算法中,我们的目的是为了求一串数组的最小乘积次数。所以我们调用动态规划的思想来解决这类问题。在动态规划的过程中,我们需要建立两组二维数组,一个用来记录每一个子问题的最优解,另一组用来记录每一组最优解断开的位置。

在写算法的时候我们设置一个P的一位数组,假设有n个矩阵,那么P[0]代表第一个矩阵的行,P[1]代表第一个矩阵的列......依次递推即P[N-1]代表第N个矩阵的行值,P[N]代表第N个矩阵的列值。

之后我们得到递推公式:————解释下这个公式:当i=j时也就意味着当前矩阵列只有一个矩阵, 此时肯定不涉及相乘的问题,所以必须是0呀。

当i<j时,我们将当前矩阵的断点设置为k,也就是第i个矩阵到第k个矩阵为一组,k+1到j为一组。遍历所有情况求解出最小的那个值(因为m[i][k]与m[k+1][j]的情况我们在求解这个问题前已经得出,所以直接拿来用就好),最后别忘了把最后一个矩阵的乘积次数加上(这个很好记——矩阵链的第一个数的行*最后一个数的列*断开位置的列)下面我给出这两个二维数组的具体过程

先处理对角线的值,之后向右以此写15750、2625、750。。。按照对角线的顺序来写,同理s矩阵中存入的是最优解断开位置,与m顺序相同。之后我们知道m[1][6]就是我们要求的最优解。

代码:

int MatrixChain(int n,int **m,int **s,int *p)  
{  
    for(int i=1; i<=n; i++)  //只有一个矩阵的情况
    {  
        m[i][i] = 0;  
    }  
    for(int r=2; r<=n; r++) 
    {  
        for(int i=1; i<=n-r+1; i++)//
        {  
            int j = i+r-1;//计算前边界为r,链长为r的链的后边界    
  
            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++)  
            {  
                //将链ij划分为( A[i:k] )* (A[k+1:j])     
                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 m[1][L-1];  
}  

 

不过动态规划的问题还是要多加练习的,如果同学们有想练手的话可以去“计蒜课”中写一下“沙子的质量”——————我对于这道题目也写了一些题解http://www.cnblogs.com/Pinging/p/7684638.html大家可以去看一看

 ————————————————————Made By Pinging

原文地址:https://www.cnblogs.com/Pinging/p/7898732.html