矩阵链相乘问题

 给出一个矩阵链,A1A2...An。求最小的相乘运算次数。
如: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 << ")";
	}
}
 
posted @ 2011-06-09 18:31  SubmarineX  阅读(746)  评论(0编辑  收藏  举报