矩阵连乘积

题目

m × \times ×n矩阵A与n × \times ×p矩阵B相乘需消耗O(mnp)的时间。我们把mnp作为两个矩阵用来相乘所需时间的测量值。
在多个矩阵连乘的情况下,不同矩阵之间的计算顺序不同结果虽然相同,但总共所需要的乘法数量不同。
例子:
A = = = ( 2 5 6 1 4 3 ) \bigl(\begin{matrix} 2 & 5 & 6\\ 1 & 4 & 3 \end{matrix} \bigr) (215463),B = = = [ [ 2 6 4 2 7 5 ] ] \bigl[ \begin{bmatrix}2 & 6\\4 & 2\\ 7 & 5\end{bmatrix} \bigr] [247625],C = = = ( 1 5 6 8 3 3 2 1 ) \bigl(\begin{matrix} 1 & 5 & 6 & 8\\ 3 & 3 & 2 &1\end{matrix} \bigr) (13536281)。计算ABC的乘法次数。
方法一:(AB)C = = = 2 × \times × 3 × \times × 2 + + + 2 × \times × 2 × \times × 4 = = = 28
方法二:A(BC) = = = 2 × \times × 3 × \times × 4 + + + 3 × \times × 2 × \times × 4 = = = 48
**注:此处细节略过,学过线性代数的小伙伴应该都知道的。

建立递归关系

我们定义A[i,j](1 ≤ \leq i ≤ \leq j ≤ \le n)所需要的最少次数为m[i][j],则原问题的最优解是m[1][n]。
状态转移方程为:

m [ i ] [ j ] = { 0 i = j min ⁡ i ≤ k < j m [ i ] [ k ] + m [ k + 1 ] [ j ] + p i − 1 p k p j i < j m[i][j] = \begin{cases} 0 & i = j \\ \min\limits_{i \leq k < j } {m[i][k] + m[k+1][j]+p_{i-1}p_kp_j} & i <j \end{cases} m[i][j]=0ik<jminm[i][k]+m[k+1][j]+pi1pkpji=ji<j

代码

#include<stdio.h>

#define NUM 51
int p[NUM];		//记录矩阵Ai的维数 
int m[NUM][NUM];//记录最优值数组 
int s[NUM][NUM];//记录最优断开位置的数组s 

void MatrixChain(int n)	//计算最优值 
{
	for(int i = 1;i <= n;i++) m[i][i] = 0;	//平凡矩阵 
	for(int r = 2;r <= n;r++)	//从第2个对角线到第n个对角线 
		for(int i = 1; i <= n-r+1;i++)	//需要填充的个数 
		{
			int j = i+r-1;//每个填充的纵坐标 
			m[i][j] = m[i+1][j] + p[i-1]*p[i]*p[j];//记录初值 
			s[i][j] = i;//从i处断开 
			for(int k = i+1; k < j;k++)//判断从i+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;
				}	
			} 
		}	
} 

void TraceBack(int i,int j)//构造最优解结构(递归) 
{
	if(i == j) printf("A%d",i);
	else{
		printf("(");
		TraceBack(i,s[i][j]);
		TraceBack(s[i][j]+1,j);
		printf(")");
	}	
} 

int main()
{
	int n;
	scanf("%d",&n);
	int i,temp;
	for(i = 0;i < n;i++) //输入A1 ~ An-1的行列数
		scanf("%d%d",&p[i],&temp);
	p[n] = temp;//输入第An个的列数 
	MatrixChain(n);
	printf("%d\n",m[1][n]);//输出最优解 
	TraceBack(1,n);//构造最优解结构 
	return 0;
}

填表

都说动态规划其实质就是一个填表的过程,代码的两层填表过程如下图所示:

d= 1d = 2d = 3d = 4d = 5d = 6
m[1,1]m[1,2]m[1,3]m[1,4]m[1,5]m[1,6]
m[2,2]m[2,3]m[2,4]m[2,5]m[2,6]
m3,3]m[3,4]m[3,5]m[3,6]
m[4,4]m[4,5]m[4,6]
m[5,5]m[5,6]
m[6,6]

输入

6
50 10
10 40
40 30
30 5
5 20
20 15

输出

15750
((A1(A2(A3A4)))(A5A6)) 

总结

怎么讲呢,学到了很多Markdown公式的写法,而矩阵连乘积正是动态规划的一个经典例子。学好动态是算法的一个深化吧!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值