問題描述: 設有三個矩陣 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