動態規劃(六)矩陣連乘問題

       矩陣連乘也是常見的動態規劃例子之一。形式如下:給出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);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章