【矩阵连乘法】“动态规划”——《算法设计与分析(第五版)》


一、算法要求

给定n个矩阵{A,A,A,,…,An},其中,Ai和Ai+1( i=1,2,…,n-1)是可乘的。用加括号的方法表示矩阵连乘的次序,不同的计算次序计算量(乘法次数)是不同的,找出一种加括号的方法,使得矩阵连乘的计算量最小。

1. 思路

给定n个矩阵{A1,A2,…,An},其中A与Ai+1是可乘的(i=1,2,…,n-1)。考察这n个矩阵的连乘积A1A2…An。由于矩阵乘法满足结合律,因此计算矩阵的连乘积可以有不同的计算次序。
这种计算次序可以用加括号的方式来确定。若一个矩阵连乘积的计算次序完全确定,也就是说,该连乘积已完全加括号,则可依此次序反复调用两个矩阵相乘的标准算法计算出矩阵连乘积。
完全加括号的矩阵连乘积可递归地定义为:
①单个矩阵是完全加括号的;
②矩阵连乘积A是完全加括号的,则A可表示为两个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC)。

	例如,矩阵连乘积A1A2A3A4可以有以下5种完全加括号方式:
	(A1(A2(A3A4))),(A1((A2A3)A4)),((A1A2)(A3A4)),((A1(A2A3))A4),(((A1A2)A3)A4)
	每种完全加括号方式对应一种矩阵连乘积的计算次序,而矩阵连乘积的计算次序与其计算量有密切关系。
	首先考虑计算两个矩阵乘积所需的计算量。
	计算两个矩阵乘积的标准算法如下,其中,ra、ca和rb、cb分别表示矩阵A和B的行数和列数。

2. 示例

在这里插入图片描述
在这里插入图片描述


二、完整代码

1. 主文件

main.cpp:

// Project1: 矩阵连乘法

#include<iostream>
using namespace std; 

const int rangeMatrix = 100;
int p[rangeMatrix];					//行列数组
int m[rangeMatrix][rangeMatrix],	//结果数组
	s[rangeMatrix][rangeMatrix];	//断点数组
int n;

// n = 5
// p[] = {3 5 10 8 2 4}

void Print(int i, int j) {
	if (i == j) {
		cout << "A["
			<< i << "]";
		return;
	}
	cout << "(";
	Print(i, s[i][j]);
	Print(s[i][j] + 1, j);
	cout << ")";
}

void MatrixChain() {
	int i, j, r, k;
	memset(m, 0, sizeof(m));	
	memset(s, 0, sizeof(s));	//初始化数组元素为0
	for (r = 2; r <= n; r++) {	//不同规模的子问题
		for (i = 1; i <= n - r + 1; i++) {
			j = i + r - 1;
			m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];//决策为k=i的乘法次数
			s[i][j] = i;					//子问题的最优策略是i
			for (k = i + 1; k < j; k++) {	//对从i到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;
				}
			}
		}
	}
}

int main() {
	cout << "#Please enter the number of matrices (n): ";
	cin >> n;
	cout << "#Please enter the 'row' of the matrix "
		<< "and the 'column' of the last matrix: ";
	int i, j;
	for (i = 0; i <= n; i++) {
		cin >> p[i];
	}
	MatrixChain();
	cout << "#Optimal matrix multiplication order is: ";
	Print(1, n);
	cout << "\n#The minimum calculation amount is:" 
		<< m[1][n] << endl;
	return 0;
}



2. 效果展示

在这里插入图片描述


三、补充

MatrixChain的运行举例:
在这里插入图片描述

在这里插入图片描述

由m[1][6]=15125可知这6个矩阵连乘积的最小运算次数为15125。
由s[1][6] = 3 可知A[1: 6]的最优计算次序为A[1: 3] A[4: 6];
由s[1][3] = 1 可知A[1: 3]的最优计算次序为A[1: 1] A[2: 3];
由s[4][6] = 5 可知A[4: 6]的最优计算次序为A[4: 5] A[6: 6];
因此最优计算次序为:(A1(A2A3))((A4A5)A6)。

算法复杂度分析:
(1)时间复杂度:
由程序可以得出:语句t=m[i][k] + m[k+1][j]+p[i-1]*p[k]*p[j],它是算法的基本语句,在3层for循环中嵌套。最坏情况下,该语句的执行次数为O(n3),print()函数算法的时间主要取决于递归,时间复杂度为O(n)。故该程序的时间复杂度为O(n3)。
(2)空间复杂度:
该程序的输入数据的数组为p[],辅助变量为i、j、r、t、k、m[]I]、s[][],空间复杂度取决于辅助空间,因此空间复杂度为O(n2)。

文档供本人学习笔记使用,仅供参考。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NI'CE'XIAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值