动态规划(六)矩阵连乘问题

       矩阵连乘也是常见的动态规划例子之一。形式如下:给出N个矩阵,矩阵是有序的,即相邻矩阵之间可以进行乘法运算,求这些矩阵最小的相乘次数。如:矩阵30*15、15*5、5*10,先让前两个矩阵进行相乘时、再和最后一个矩阵相乘时,乘法计算次数为30*15*5+30*5*10=3750,;先让后两个矩阵相乘、再和第一个矩阵相乘时,乘法计算次数为15*5*10+30*15*10=5250。由此可见,不同的运算顺序,会影响到乘法的计算次数。

       首先假设以下变量:

           n表示矩阵的个数
           Ai表示第i个矩阵
           A[i:j]表示矩阵连乘AiA{i+1}..Aj
           pi表示Ai的列数
           p{i-1}表示Ai的行数
           k表示矩阵连乘断开的位置为k,表示在Ak和A{k+1}之间断开
           m[i,j]表示A[i:j]的最少乘次,m[1,n]即问题的最优解

        假设k是对矩阵链A[i:j]一分为二得到最优解时的断开位置,则m[i,k]和m[k+1,j]分别是两个子矩阵链A[i,k]和A[k+1,j]的最优解。两个矩阵最后要相乘才能得到A[i,j],因此,最后要加上p{i-1}*pk*pj,也就是两子矩阵相乘的数乘次数,才能得到总的数乘次数。公式如下:

                                    

        Java代码如下:

            int arr[ ] = {30,15,5,10}; 
            int minMultiplication = 0;
            final int LENGTH = arr.length;
            int[ ][ ] s = new int [ LENGTH ][ LENGTH ];  
            int[ ][ ] m = new int [ LENGTH ][ LENGTH ];  
            for(int i=0;i<LENGTH;i++)    
            {    
                 for(int j=0;j<LENGTH;j++){ 
                     s[ i ][ j ] = 0;  
                     m[ i ][ j ] = 0;  
                 }
             }   
        
            for(int r=2; r<=LENGTH-1; r++)      //r为当前计算的链长(子问题规模)    
            {  
                   for(int i=1; i<=LENGTH-1-r+1; i++)//LENGTH-1-r+1为最后一个r链的前边界    
                   {  
                          int j = i+r-1;//计算前边界为r,链长为r的链的后边界    
                          m[ i ][ j ] = m[ i+1 ][ j ] + arr[ i-1 ]*arr[ i ]*arr[ j ];//将链ij划分为A(i) * ( A[i+1:j] )   
                          s[ i ][ j ] = i;  //s[ ][ ]存储各子问题的决策

                          for(int k=i+1; k<j; k++)  //将链ij划分为( A[i:k] )* (A[k+1:j])    
                          {  
                                 int tmp = m[ i ][ k ] + m[ k+1 ][ j ] + arr[ i-1 ]*arr[ k ]*arr[ j ];  
                                 if(tmp<m[ i ][ j ])  
                                 {  
                                       m[ i ][ j ] = tmp;  
                                       s[ i ][ j ] = k;  
                                  }  
                           }  
                    }  
             } 
        
              minMultiplication = m[1][LENGTH-1];
              System.out.println(minMultiplication);

原创文章 9 获赞 0 访问量 599

猜你喜欢

转载自blog.csdn.net/m0_37741420/article/details/105467776