当前位置:首页 > 技术 > 正文内容

矩阵链乘法的最优括号化方案与C++算法实现

访客 技术 2026年9月18日 10

在处理多个矩阵连续相乘(矩阵链乘法)时,不同的结合顺序会导致标量乘法次数的巨大差异。对于少量矩阵的相乘,枚举所有情况即可找到最优解;但当矩阵数量增加时,必须借助算法来寻找最优的括号化方案,以最小化计算代价。以下将分别探讨基于记忆化搜索和动态规划的两种高效求解策略。

自顶向下:记忆化搜索

记忆化搜索(Memoization)通过递归分解问题,并利用二维缓存数组记录已解决的子问题结果,从而避免重复计算。这种方法保留了递归的直观逻辑,同时将时间复杂度从指数级降低到多项式级。在实现时,我们使用一维数组存储矩阵的维度信息,其中第 i 个矩阵的维度为 dims[i-1] × dims[i]。


#include <iostream>
#include <vector>
#include <climits>

using namespace std;

// 递归函数,计算矩阵链 dims[start...end] 的最小乘法次数
int solveMemoized(const vector<int>& dims, int start, int end, vector<vector<int>>& cache) {
    // 单个矩阵无需进行乘法运算
    if (start == end) {
        return 0;
    }
    
    // 如果子问题已经计算过,直接返回缓存结果
    if (cache[start][end] != -1) {
        return cache[start][end];
    }
    
    int minCost = INT_MAX;
    
    // 尝试所有可能的分割点
    for (int split = start; split < end; ++split) {
        int cost = solveMemoized(dims, start, split, cache) 
                 + solveMemoized(dims, split + 1, end, cache) 
                 + dims[start - 1] * dims[split] * dims[end];
                 
        if (cost < minCost) {
            minCost = cost;
        }
    }
    
    // 将最优解存入缓存并返回
    cache[start][end] = minCost;
    return minCost;
}

int main() {
    int numMatrices;
    if (!(cin >> numMatrices)) return 0;
    
    // 维度数组大小为 numMatrices + 1
    vector<int> dims(numMatrices + 1);
    for (int i = 0; i <= numMatrices; ++i) {
        cin >> dims[i];
    }
    
    // 初始化缓存表,-1 表示尚未计算
    vector<vector<int>> cache(numMatrices + 1, vector<int>(numMatrices + 1, -1));
    
    int minMultiplications = solveMemoized(dims, 1, numMatrices, cache);
    cout << minMultiplications << endl;
    
    return 0;
}

自底向上:动态规划

自底向上的动态规划(Dynamic Programming)摒弃了递归调用,通过迭代的方式按矩阵链长度递增的顺序填充状态表。这种方法不仅避免了递归带来的函数调用栈开销,还在空间局部性上表现更优,是解决此类区间DP问题的标准范式。


#include <iostream>
#include <vector>
#include <climits>

using namespace std;

int main() {
    int numMatrices;
    if (!(cin >> numMatrices)) return 0;
    
    vector<int> dims(numMatrices + 1);
    for (int i = 0; i <= numMatrices; ++i) {
        cin >> dims[i];
    }
    
    // dp[i][j] 表示计算矩阵链 Ai 到 Aj 所需的最小标量乘法次数
    vector<vector<int>> dp(numMatrices + 1, vector<int>(numMatrices + 1, 0));
    
    // chainLen 代表当前计算的矩阵链长度,从 2 开始递增
    for (int chainLen = 2; chainLen <= numMatrices; ++chainLen) {
        for (int start = 1; start <= numMatrices - chainLen + 1; ++start) {
            int end = start + chainLen - 1;
            dp[start][end] = INT_MAX;
            
            // 遍历分割点,寻找最小代价
            for (int split = start; split < end; ++split) {
                int cost = dp[start][split] + dp[split + 1][end] 
                         + dims[start - 1] * dims[split] * dims[end];
                         
                if (cost < dp[start][end]) {
                    dp[start][end] = cost;
                }
            }
        }
    }
    
    // 输出整个矩阵链的最小乘法次数
    cout << dp[1][numMatrices] << endl;
    
    return 0;
}
标签: 矩阵链乘法

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。