矩阵连乘积

博客围绕矩阵连乘问题展开,指出多个矩阵连乘时不同计算顺序所需乘法数量不同。通过定义最少次数建立递归关系,给出状态转移方程。还提到动态规划实质是填表过程,最后总结学习到Markdown公式写法,强调矩阵连乘是动态规划经典例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

m×\times×n矩阵A与n×\times×p矩阵B相乘需消耗O(mnp)的时间。我们把mnp作为两个矩阵用来相乘所需时间的测量值。
在多个矩阵连乘的情况下,不同矩阵之间的计算顺序不同结果虽然相同,但总共所需要的乘法数量不同。
例子:
A === (256143)\bigl(\begin{matrix} 2 & 5 & 6\\ 1 & 4 & 3 \end{matrix} \bigr)(215463),B === [[264275]]\bigl[ \begin{bmatrix}2 & 6\\4 & 2\\ 7 & 5\end{bmatrix} \bigr][247625],C === (15683321)\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]={0i=jmin⁡i≤k<jm[i][k]+m[k+1][j]+pi−1pkpji<jm[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公式的写法,而矩阵连乘积正是动态规划的一个经典例子。学好动态是算法的一个深化吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值