当前位置: 首页 > news >正文

MIT-矩阵链相乘

文章目录

  • 问题描述
  • 例子
  • 算法实现
    • 暴力枚举
    • 动态规划

问题描述

假设你要计算矩阵乘积:

A1A2A3⋯AnA_1A_2A_3\cdots A_nA1A2A3An

矩阵相乘虽然结合律成立(即A(BC)=(AB)CA(BC)=(AB)CA(BC)=(AB)C),但 乘法次数不同!

❗ 所以不同的加括号方式(计算顺序)会导致 乘法次数差距极大。

例子

假设我们有三个矩阵:

  • A1A_1A110×10010 \times 10010×100
  • A2A_2A2100×5100 \times 5100×5
  • A3A_3A35×505 \times 505×50

1️⃣ (A1A2)A3(A_1A_2)A_3(A1A2)A3

  • 先算(A1A2)(A_1A_2)(A1A2):需要 (10 × 100 × 5 = 5000) 次乘法
    结果矩阵是 (10×5)
  • 再算 (A1A2)A3(A_1A_2)A_3(A1A2)A3:需要 (10 × 5 × 50 = 2500) 次乘法
    总共:7500 次

2️⃣ A1(A2A3)A_1(A_2A_3)A1(A2A3)

  • 先算(A2A3)(A_2A_3)(A2A3):需要 (100 × 5 × 50 = 25000) 次乘法
    结果矩阵是 (100×50)
  • 再算 A1(A2A3)A_1(A_2A_3)A1(A2A3):需要 (10 × 100 × 50 = 50000) 次乘法
    总共:75000 次

🔥 差距是 10倍!
所以要找出“最优加括号方式”才能最省时间。

算法实现

暴力枚举

卡特兰数:设 h(n)h(n)h(n) 为卡特兰数的第 nnn 项,令 h(0)=1,h(1)=1h(0)=1,h(1)=1h(0)=1,h(1)=1,则卡特兰数满足递推式:

h(n)=h(0)×h(n−1)+h(1)×h(n−2)+⋯+h(n−1)×h(0)=∑k=0n−1h(k)h(n−1−k)(n≥2)h(n)=h(0)\times h(n-1)+h(1)\times h(n-2)+\cdots+h(n-1)\times h(0)=\sum_{k=0}^{n-1}h(k)h(n-1-k)(n\geq2)h(n)=h(0)×h(n1)+h(1)×h(n2)++h(n1)×h(0)=k=0n1h(k)h(n1k)(n2)

h(n)=C2nnn+1(n∈N)h(n)=\frac{C_{2n}^n}{n+1}(n\in N)h(n)=n+1C2nn(nN)

nnnh(n)h(n)h(n)
01
11
22
35
414

我们定义 f(n)f(n)f(n)nnn 个矩阵相乘时不同的加括号方式数目。
例如:

  • f(1)=1f(1)=1f(1)=1:一个矩阵不需要括号;
  • f(2)=1f(2)=1f(2)=1:两个矩阵只有一种乘法方式;
  • f(3)=2f(3)=2f(3)=2:三矩阵可以是 (A1A2)A3(A_1A_2)A_3(A1A2)A3A1(A2A3)A_1(A_2A_3)A1(A2A3)

故有:

f(n)=∑k=1n−1f(k)f(n−k)f(n)=\sum_{k=1}^{n-1}f(k)f(n-k)f(n)=k=1n1f(k)f(nk)

  • nnn 个矩阵分成两部分:
    (A1A2⋯Ak)(Ak+1Ak+2⋯An)(A_1A_2\cdots A_k)\left(A_{k+1}A_{k+2}\cdots A_n\right)(A1A2Ak)(Ak+1Ak+2An)
  • 前面那部分的加括号方式有 f(k)f(k)f(k) 种;
  • 后面那部分有 f(n−k)f(n-k)f(nk) 种;
  • 这两部分组合起来就是 f(k)×f(n−k)f(k) \times f(n-k)f(k)×f(nk) 种;
  • 最后对所有可能的 kkk 求和。
nnnf(n)f(n)f(n)
11
21
32
45
514

观察可知

f(n)=h(n−1)f(n)=h(n-1)f(n)=h(n1)

也就是说 fff 比 卡特兰数 hhh 的下标大 1。

所以

f(n)=C2n−2n−1n=(2n−2)!n((n−1)!)2f(n)=\frac{C_{2n-2}^{n-1}}{n}=\frac{(2n-2)!}{n((n-1)!)^2}f(n)=nC2n2n1=n((n1)!)2(2n2)!

其中 n!n!n! 可近似为:

n!≈2πn(ne)nn!\approx\sqrt{2\pi n}\left(\frac{n}{e}\right)^nn!2πn(en)n

(2n−2)!≈2π(2n−2)(2n−2e)2n−2=22n−1π(n−1)(n−1e)2n−2(2n-2)!\approx\sqrt{2\pi (2n-2)}\left(\frac{2n-2}{e}\right)^{2n-2}=2^{2n-1}\sqrt{\pi(n-1)}(\frac{n-1}{e})^{2n-2}(2n2)!2π(2n2)(e2n2)2n2=22n1π(n1)(en1)2n2
(n−1)!≈2π(n−1)(n−1e)n−1=20.5π(n−1)(n−1e)n−1(n-1)!\approx\sqrt{2\pi (n-1)}\left(\frac{n-1}{e}\right)^{n-1}=2^{0.5}\sqrt{\pi(n-1)}(\frac{n-1}{e})^{n-1}(n1)!2π(n1)(en1)n1=20.5π(n1)(en1)n1

f(n)=(2n−2)!n((n−1)!)2≈22n−2nπ(n−1)≈4n4n1.5πf(n)=\frac{(2n-2)!}{n((n-1)!)^2}\approx \frac{2^{2n-2}}{n\sqrt{\pi(n-1)}}\approx\frac{4^n}{4n^{1.5}\sqrt{\pi}}f(n)=n((n1)!)2(2n2)!nπ(n1)22n24n1.5π4n

f(n)=O(4nn1.5)f(n)=O(\frac{4^n}{n^{1.5}})f(n)=O(n1.54n)

这是一个极其庞大的数!一个一个枚举显然不合适!


动态规划

维度数组p0p_0p0 是第一个矩阵的行数,p1p_1p1 是第一个矩阵的列数,第二个矩阵的行数。

p=[p0,p1,p2,…,pn]p=[p_0,p_1,p_2,\ldots,p_n]p=[p0,p1,p2,,pn]

  • A1A_1A1 矩阵的维数是 p0×p1p_0\times p_1p0×p1A1A2A_1A_2A1A2 矩阵的维数是 p0×p2p_0\times p_2p0×p2A2A3A_2A_3A2A3 矩阵的维数是 p1×p3p_1\times p_3p1×p3,… ,A1…AnA_1\ldots A_nA1An 矩阵的维数是 p0×pnp_0\times p_np0×pn
  • A1(A2A3)A_1(A_2A_3)A1(A2A3)所需的计算次数为 p0×p1×p3p_0\times p_1 \times p_3p0×p1×p3

状态定义: 此时我们定义 dp[i][j]dp[i][j]dp[i][j] 是计算矩阵 AiAi+1⋯AjA_iA_{i+1}\cdots A_jAiAi+1Aj 所需的最少乘法次数。

初始化:dp[i][j]dp[i][j]dp[i][j] 中的 i==ji==ji==j 时,表示一个矩阵所需的最少乘法次数,即 dp[i][i]=0dp[i][i] = 0dp[i][i]=0

转移方程: 如果在第 k(i≤k<j)k(i\leq k< j)k(ik<j) 处分割:

则:

dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+p[i−1]p[k]p[j])dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+p[i-1]p[k]p[j])dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+p[i1]p[k]p[j])

请添加图片描述
请添加图片描述

int DPmatrixChain(int p[], int n)
{int dp[n + 1][n + 1];/* 初始化操作 */for (int i = 1; i <= n; i ++ ) dp[i][i] = 0;/* 错误操作for (int i = 1; i <= n; i ++ ) 这样的循环会出现所用到更小的子问题,并没有出现在表中for (int j = i + 1; j <= n; j ++ )for (int k = i; k < j; k ++ )dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + p[i - 1] * p[k] *  p[j]);  dp[i][j] 依赖于比它“短”的子区间的值*//* 正确操作:当我要求解一个子问题时,它所依赖的更小子问题的结果已经在表中 */for (int len = 2; len <= n; len ++ )for (int i = 1; i <= n - len + 1; i ++ ){int j = i + len - 1;dp[i][j] = INT_MAX;for (int k = i; k < j; k ++ )      // 枚举分割点dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + p[i - 1] * p[k] * p[j]);}return dp[1][n];
}

时间复杂度O(n3)O(n^3)O(n3)

http://www.dtcms.com/a/576984.html

相关文章:

  • Go语言实战:入门篇-5:函数、服务接口和Swagger UI
  • 国产化Excel处理控件Spire.XLS教程:使用Java将CSV转换为PDF(含格式设置)
  • 【Hot100|3 LeetCode 128. 最长连续序列】
  • 一键搭建 Coze 智能体对话页面:支持流式输出 + 图片直显,开发效率拉满!
  • 十大免费ae模板网站短视频素材下载网站
  • 那里做直播网站网页打不开是什么问题
  • 论文分享 | AirRoom:物体是关键!革新室内房间重识别的新范式
  • 游戏 IPA 如何防修改,面向开发者的多工具实战(IPA 加固/无源码混淆/Ipa Guard CLI)
  • 从0到1做一个“字母拼词”Unity小游戏(含源码/GIF)- 项目的创建及准备
  • 在扣子上搭建测试用例自动编写智能体
  • 2023年第二十届五一数学建模竞赛-A题 无人机定点投放问题-基于抛体运动的无人机定点投放问题研究
  • 影刀RPA一键生成销售日报!AI智能分析,效率提升1000%[特殊字符]
  • Rust开发实战之密码学基础——哈希计算与对称加密实战
  • 技术解析:清洗无人机在高空清洁中的应用与优势
  • Linux LVM NAT 模式部署实践
  • 使用 DVC(Data Version Control)进行数据版本管理
  • 网站建设选择哪种开发语言最好从哪里下载wordpress
  • 微服务之网关(Spring Cloud Gateway)
  • ES脚本语言Painless介绍
  • 基于MATLAB的雨流计数法疲劳计算GUI可视化系统
  • WiFi 协议精读:IEEE 802.11-2012,IEEE Std 802.11w™-2009: Protected Management Frames
  • RabbitMQ-Exporter 监控 TLS 加密的 RabbitMQ 集群
  • 重庆佳宇建设集团网站重庆网站自己推广
  • 品牌营销策划网站wordpress 会员开卡消费
  • iOS修改tabbar的背景图
  • 《uni-app跨平台开发完全指南》- 04 - 页面布局与样式基础
  • 【学习笔记更新中】Deeplearning.AI 大语言模型后训练:微调与强化学习导论
  • SQL之表的时间类内置函数详解
  • 线性代数 - 奇异值分解(SVD Singular Value Decomposition)- 计算顺序 旋转→拉伸→旋转
  • html的input的required