动态规划算法之矩阵链乘法

设有一个矩阵链A1*A2*A3,其维度为30*35,35*15,15*5。不同的结合性,需要的矩阵乘法数量不同,m[(A1*A2)*A3] = 30*35*15+0+30*15*5 = 18000,而m[A1*(A2*A3)] = 0+35*15*5+30*35*5 = 7875。所以,结合性在A1后面划分,运算量最小。

对于矩阵链A1*A2*A3*......*An,假设矩阵都是相容的,如果用递归的方法解,其复杂度为Ω(2^n)(有证明),而动态规划的复杂度为Ω(n^3)+seta(n^2)。

动态规划算法的四步:1、描述最优解的结构:对于矩阵链A(i)A(i+1)......A(j),若存在i<=k<j,使得A(i)A(i+1)......A(k)、A(k+1)......A(j)、两个子结构之积,这三者代价之和最小,那么k为其中一个划分。同时两个子结构为最优子结构。2、定义最优解的值:m[i,j] = min{m[i,k]+m[k+1,j]+p(i-1)pkpj}    (i<j,i<=k<j)和m[i,j] = 0   (i=j)。3、由低向上计算最优解的值:对于矩阵链A1*A2*A3*......*An,自左往右,首先计算步长为1的最优解,步长依次递增,直到求步长为n-1的最优解。其中m[i,j]存最优解代价,s[i,j]存放最优解的划分位置。4、根据S[i,j]就能够求的具体的划分了。

伪代码:

图1

下面是具体代码实现:

#include<stdio.h>
int PrintDivi(int (*p)[6], int start, int end)
{
	int Divi;
	Divi = p[start][end];
	if(start == end)
		printf("A%d",start+1);
	else
	{
		printf("(");
		PrintDivi(p, start, Divi);
		PrintDivi(p, Divi+1, end);
		printf(")");
	}
}
int main(void)
{
	int l,i,j,k,temp;
	int p[7] = {30,35,15,5,10,20,25};
	int m[6][6],s[6][6];
	for(i=0;i<6;i++)
	{		
		m[i][i] = 0;
	}
	for(l=2;l<=6;l++)
		for(i=0;i<6-l+1;i++)
		{
			j=i+l-1;
			m[i][j] = 0x7fffffff;
			for(k=i;k<j;k++)
			{
				temp = m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];
				if(temp<m[i][j])
				{
					m[i][j] = temp;
					s[i][j] = k;
				}
			}
		}
	PrintDivi(s, 0, 5);
	return 0;
}
参考书目:《算法导论》第二版

猜你喜欢

转载自blog.csdn.net/zhangjiajieshiyongdi/article/details/12348311
今日推荐