動態規劃 (Dynamic Programming) 之 矩陣鏈乘法(Matrix Chain Multiplication)
這個問題是動態規劃的基礎的問題,也是演算法導論中討論過的問題。在這裡先簡單描述一下。假定有一組矩陣需要做乘法操作。但是我們知道首先矩陣乘法滿足了結合律。所以可以按照不同的順序做乘法。而且不同順序做乘法最後的乘法次數是不同的。比如〈A1, A2, A3〉分別是10 × 100, 100 × 5, 和 5 × 50。如果按照((A1A2) A3)的順序來計算,就是7500次,但是如果(A1 (A2A3))這樣的順序,那結果就是75000次!!!這裡有10倍的差距。所以這個題目的意思就是找到一個方案使得需要做乘法的次數最少。
現在我們嘗試用大白話來繼續一下。問題的解決方案側重在兩個方面。一個是最少乘法的次數,另一個就是最小乘法次數的流程。在程式碼中我們分別用m,s來表示。先說一下m的含義。m是個二維陣列,m[i,j]表示從矩陣i到矩陣j的最小乘法次數。也就是A[i],A[i+1]....A[j]的最小乘法次數。可以發現,這個次數應該等於A[i],A[i+1]...A[k] * A[k+1]....A[j-1]A[j]的次數,這裡的k是輸入i到j這個開區間的某個數。找到這個數字,我們也就找到了最小乘法次數。
那怎麼找到這個數字呢?簡單的說就是把所有的可能性都列舉出一遍k=i, i+1, i+2...j都嘗試一遍。比較最小值就可以了。有了這個思路我們可以把遞迴公式寫成:
這裡的p就是你的矩陣維數的陣列。
根據這個公式,我們可以寫出下面的程式碼:
需要注意的問題是,這個演算法的複雜度在O(n∧3)。而且這個演算法和演算法導論等地方的偽碼比有些細微的差異體現在陣列從0開始還是1開始上。大體上還是一致的。這裡的空間複雜度也到了O(n∧2)。大致的計算順序就是通過這個函式中的l來控制。l=2的時候,依次計算矩陣A[0]*A[1], A[1]*A[2], A[2]*A[3]...的次數。l=3的時候就開始計算A[0]*A[1]*A[2], A[1]*A[2]*A[3]..的次數。用更形象的話來說就是倒三角的順序。下面的這個圖就是對上面流程的描述:
最後說一句,這個矩陣鏈問題是相對獨立的一個問題,和其他的知名的問題都沒有太大的關聯。以後的總結可能有很多不同的變形。