当多个连续可乘矩阵做乘法时,选择正确的做乘顺序可以有效减少做乘法的次数,而选择的方法可以很容易的通过DP实现。
原理就是对于每一个所求矩阵,搜索所有可以相乘得到它的方法,比较它们的消耗,选取最小值作为采用的方法。
例如,给出矩阵A1(30*35) A2(35*15) A3(15*5) A4(5*10) A5(10*20) A6(20*25)
我们另m(i,j)表示从第i个矩阵乘到第j个矩阵,并用p[i]表示矩阵的边长,如p[0]=30,p[1]=35......
于是我们有:
若i==j m(i,j)=0
若i<j m(i,j)=min(m(i,k)+m(k+1,j)+p[i-1]*p[k]*p[j]),k=i,i+1,i+2...j-1(i<=k<j)
实际操作过程中,我们往往用数组来记录每一个我们已经计算过的m(i,j)来提高效率。
代码如下:
主算法:
#pragma once #include <algorithm> int matrix_p[MAX_V]; int m[MAX_V][MAX_V]; int matrix_V; int matrix_mul(int i, int j) { if (m[i][j] == INF) { for (int k = i;k < j;++k) { m[i][j] = std::min(m[i][j], matrix_mul(i, k) + matrix_mul(k + 1, j) + matrix_p[i - 1] * matrix_p[k] * matrix_p[j]); } } return m[i][j]; }
主程序:
void matrix_chain_test() { cin >> matrix_V; for (int i = 0;i <= matrix_V;++i) cin >> matrix_p[i]; for (int i = 0;i <= matrix_V;++i) { for (int j = 0;j <= matrix_V;++j) { m[i][j] = INF; } m[i][i] = 0; } int i, j; while (true) { cin >> i >> j; if (i == -1) break; cout << matrix_mul(i, j) << endl; } }
PS:INF和MAX_V是两个很大的数,具体大家自己定就行。