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

矩阵链相乘的最少乘法次数(动态规划解法)

矩阵链相乘问题是动态规划的经典应用场景。当多个矩阵相乘时,不同的相乘顺序会导致乘法运算的总次数差异巨大。我们的目标是找到一种相乘顺序,使得总的乘法次数最少。

问题分析

假设有矩阵序列 A1​,A2​,…,An​,其中 Ai​ 的维度为 pi−1​×pi​。矩阵相乘满足结合律,但不同的结合方式会影响乘法运算的总次数。例如,三个矩阵 A(10×30)、B(30×5)、C(5×60),按 (AB)C 计算的乘法次数为 10×30×5+10×5×60=4500,按 A(BC) 计算的乘法次数为 30×5×60+10×30×60=27000,显然前者更优。


矩阵相乘的基本逻辑

当我们有一组维度数据,比如 74 16 58,它能构成两个矩阵:矩阵 a 的维度是 [74,16](对应数据的第 i 和 i+1 个元素),矩阵 b 的维度是 [16,58](对应数据的第 i+1 和 i+2 个元素)。

矩阵 a 和 b 相乘时,乘法次数的计算方式为 74×58×16。相乘之后,会得到一个新的矩阵,其维度为 [74,58],后续可继续与其他矩阵相乘。


问题核心:寻找最少乘法次数

我们的目标是,对于由 n 个矩阵组成的链,找到一种相乘顺序,使得总的乘法次数最少。

以包含 6 个维度数据(对应 5 个矩阵 a b c d e)的情况为例:

  • 两个矩阵相乘时,只有 1 种组合情况(如 ab)。
  • 三个矩阵相乘时,有 2 种组合情况(如 a(bc) 或 (ab)c)。
  • 四个矩阵相乘时,有 3 种组合情况(如 a(bcd)、(ab)(cd) 或 (abc)d)。
  • 以此类推,n 个矩阵相乘时,会有 n−1 种组合情况。

可以发现,不管有多少个矩阵相乘,每种组合情况都是将所有矩阵分成两部分。这一特性表明,矩阵链相乘问题具有最优子结构,非常适合用动态规划来解决。

动态规划的思路推导

以 4 个矩阵(对应 5 个维度数据 74 16 58 58 88)的情况为例,这 4 个矩阵分别是 a[74,16]、b[16,58]、c[58,58]、d[58,88]。

1. 设定断点分割矩阵链

我们可以设定一个断点 k(范围是 1 到 n),表示在第 k 个矩阵后将整个矩阵链隔开。

比如,当断点 k=2 时,矩阵链被分成两部分:ab 和 cd。

2. 子问题的最少乘法次数计算
  • 计算 ab 部分的最少乘法次数:ab 相乘的次数为 74×58×16,得到新矩阵维度为 [74,58],这部分的最少次数用 dp[1][2] 表示(dp[i][j] 表示从第 i 个矩阵到第 j 个矩阵相乘的最少次数)。
  • 计算 cd 部分的最少乘法次数:cd 相乘的次数为 58×88×58,得到新矩阵维度为 [58,88],这部分的最少次数用 dp[3][4] 表示。
3. 整体最少乘法次数的计算

此时,整个矩阵链 abcd 的最少乘法次数 dp[1][4] 就等于 ab 部分的最少次数 dp[1][2] 加上 cd 部分的最少次数 dp[3][4],再加上将这两部分结果矩阵相乘的次数 74×88×58(即 i×(j+1)×(k+1),其中 i=1,j=4,k=2)。

再比如,当断点 k=1 时,矩阵链被分成 a 和 bcd 两部分:

  • a 是单个矩阵,无需计算乘法次数。
  • 对于 bcd 部分,又存在多种分割情况(如 b(cd) 或 (bc)d),需要先求出 bcd 部分的最少乘法次数 dp[2][4](取这些分割情况中的最小值)。
  • 最后,整个矩阵链 abcd 的最少乘法次数 dp[1][4] 等于 bcd 部分的最少次数 dp[2][4] 加上将 a 与 bcd 结果矩阵相乘的次数 i×(j+1)×(k+1)(其中 i=1,j=4,k=1)。

四、核心公式与递推过程

通过对各种分割情况的分析,我们可以总结出状态转移公式
dp[i][j] = min​{dp[i][k] + dp[k+1][j] + nums[i]×nums[j+1]×nums[k+1]}

其中,nums 是存储矩阵维度的数组,dp[i][j] 表示从第 i 个矩阵到第 j 个矩阵相乘的最少次数。

递推过程是:

  1. 先计算长度为 2 的矩阵链的最少乘法次数(如 dp[1][2]、dp[2][3] 等)。
  2. 基于长度为 2 的结果,计算长度为 3 的矩阵链的最少乘法次数(如 dp[1][3]、dp[2][4] 等)。
  3. 以此类推,逐步计算更长的矩阵链,每次都取当前所有可能分割情况中的最少乘法次数,直到得到整个矩阵链(从第 1 个到第 n 个矩阵)的最少乘法次数 dp[1][n]。

代码实现

#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>  // 用于INT_MAX的定义
using namespace std;// 计算矩阵链相乘的最少乘法次数
// nums:存储矩阵维度的数组,nums[1..n]有效,对应n-1个矩阵
// n:维度数组的长度(矩阵数量为n-1)
void matrixChainMinMultiplications(vector<int>& nums, int n) {// dp[i][j]表示第i个矩阵到第j个矩阵相乘的最少乘法次数vector<vector<int>> dp(n, vector<int>(n, 0));// 遍历矩阵链的长度,从2开始(至少需要2个矩阵才能相乘)for (int length = 2; length <= n - 1; ++length) {// 遍历所有可能的起始矩阵ifor (int i = 1; i + length - 1 <= n - 1; ++i) {int j = i + length - 1;  // 计算对应的结束矩阵jdp[i][j] = INT_MAX;      // 初始化为最大整数,用于后续取最小值// 遍历所有可能的分割点k,寻找最优分割for (int k = i; k < j; ++k) {// 状态转移:当前分割的乘法次数 = 左半部分最少次数 + 右半部分最少次数 + 当前分割的乘法次数dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + nums[i] * nums[j + 1] * nums[k + 1]);}}}// 输出从第1个矩阵到第n-1个矩阵相乘的最少乘法次数cout << dp[1][n - 1] << endl;
}int main() {int n;// 多组数据输入,直到输入结束while (cin >> n) {vector<int> nums(n + 1);  // 维度数组,索引1到n有效for (int i = 1; i <= n; ++i) {cin >> nums[i];}matrixChainMinMultiplications(nums, n);}return 0;
}

代码注释说明

  • matrixChainMinMultiplications 函数:核心动态规划逻辑,计算矩阵链相乘的最少乘法次数。
    • 首先初始化 dp 数组,dp[i][j] 表示第 i 到第 j 个矩阵相乘的最少次数。
    • 外层循环按矩阵链长度 length 递增遍历,确保先计算短链,再利用短链结果计算长链。
    • 中层循环遍历所有可能的起始矩阵 i,并计算对应的结束矩阵 j
    • 内层循环遍历分割点 k,通过状态转移方程更新 dp[i][j] 为最小值。
  • main 函数:处理多组输入数据,读取矩阵维度数组并调用核心函数计算结果。
  • 示例运行

    输入

    6
    10 1 50 50 20 5

        输出:      

33000

这种动态规划方法的时间复杂度为 O(n3),空间复杂度为 O(n2),能够高效解决矩阵链相乘的最少乘法次数问题。

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

相关文章:

  • KVM虚拟化技术解析:从企业应用到个人创新的开源力量
  • Langfuse2.60.3:独立数据库+docker部署及环境变量详细说明
  • AutoDL使用学习
  • 第二十八节 业务代表模式
  • Custom SRP - Baked Light
  • tree组件(几种不同分叉树Vue3)
  • Qt QDateTime时间部分显示为全0,QTime赋值后显示无效问题【已解决】
  • 从零开始大模型之实现GPT模型
  • 黑板架构详解
  • Wi-Fi 7 将如何重塑互联工作场所
  • 链式二叉树的基本操作——遍历
  • 《从入门到高可用:2025最新MySQL 8.0全栈速通指南》
  • docker-compose-mysql-定时备份数据库到其他服务器脚本
  • SpringBoot 集成Ollama 本地大模型
  • mysql的group by函数怎么使用
  • Java内功修炼(1)——时光机中的并发革命:从单任务到Java多线程
  • [Linux] Linux文件系统基本管理
  • 基于STM32的精确按键时长测量系统
  • 一周学会Matplotlib3 Python 数据可视化-绘制自相关图
  • 2020/12 JLPT听力原文 问题二 2番
  • Pycaita二次开发基础代码解析:交互选择、参数化建模与球体创建的工业级实现
  • 415. 字符串相加
  • dify 调用本地的 stable diffusion api生成图片的工作流搭建
  • 分布式存储与存储阵列:从传统到现代的存储革命
  • Windows Manager:全方位优化你的Windows系统
  • PCB高频板与普通电路板的核心差异
  • JavaScript 闭包与递归深度解析:从理论到实战
  • [优选算法专题二滑动窗口——最大连续1的个数 III]
  • 【轨物方案】预防性运维:轨物科技用AI+机器人重塑光伏电站价值链
  • K8S的ingress