矩阵链相乘问题
给出一个矩阵链,A1A2...An。求最小的相乘运算次数。
如:n*k 的 Ai 和 k*m 的A(i+1),则相乘运算次数为n*k*m。
如:n*k 的 Ai 和 k*m 的A(i+1),则相乘运算次数为n*k*m。
给AiA(i+1)...A加括号(1≤i≤j≤n),求最小代价,用m[i][j]来记录Ai...Aj最小的矩阵乘法运算次数,那么A1...An的最优解就是m[1][n]。
当只有一个矩阵时,m[i][i] = 0 (i = 1,2...,n);
当多个矩阵时,即 i<j,通过加括号来构造子结构。在Ak处把一个矩阵链划分成两个链,即Ai...Aj划分成Ai...Ak, A(k+1)...Aj(i≤k<j)。Ai...kA(k+1)...j的乘法运算次数就是p[i-1]p[k]p[j],所以得到m[i][j] = m[i][k] + m[k+1][j] + p[i-1]p[k]p[j];
递归方程如下:
m[i][j] = 0, i = j;
m[i][j] = min(i≤k<j){m[i][k] + m[k+1][j] + p[i-1]p[k]p[j]}, i < j.
/** * @brief 求最优矩阵链乘 * @param p 一个序列, Ai 为 p[i-1] * p[i] 的矩阵 * @param pLength 序列长度 * @param m m[i][j]记录Ai...Aj最小乘法运算次数 * @param s s[i][j]记录Ai...Aj最小乘法运算次数时k值 */ void MatricChainOrder(int p[], int pLength, int m[][MAXN+10], int s[][MAXN+10]) { int n = pLength - 1, chainLen, i, j, k, q; for (i = 1; i <= n; i++) { m[i][i] = 0; } for (chainLen = 2; chainLen <= n; chainLen++) { for (i = 1; i <= n - chainLen + 1; i++) { j = i + chainLen - 1; m[i][j] = INT_MAX; for (k = i; k <= j - 1; k++) { q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; if (q < m[i][j]) { m[i][j] = q; s[i][j] = k; } } } } }
/** * @brief 打印加括号的方案 */ void PrintOptimalParens(int s[][MAXN+10], int i, int j) { if (i == j) { cout << "A" << i; } else { cout << "("; PrintOptimalParens(s, i, s[i][j]); PrintOptimalParens(s, s[i][j] + 1, j); cout << ")"; } }
/**************************************************************************
                 
原文来自博客园——Submarinex的博客: www.cnblogs.com/submarinex/               
 
*************************************************************************/