在计算机科学和算法设计中,矩阵链乘法是一个经典的动态规划问题。它解决的是:给定一串矩阵,如何通过添加括号的方式,使得计算这些矩阵连乘时所需的标量乘法次数最少。虽然矩阵乘法满足结合律(即无论怎么加括号,最终结果相同),但不同的括号化方式会导致计算效率天差地别。
本教程将用通俗易懂的语言,手把手教你理解并用 Java 实现矩阵链乘法的最优解法,即使你是编程小白也能轻松掌握!
假设有三个矩阵 A、B、C,维度分别为:
有两种乘法顺序:
可见,括号的位置对性能影响巨大。我们的目标就是找到最优括号化方案,使总乘法次数最少。

我们使用动态规划来解决这个问题。核心思想是:将大问题分解为子问题,并保存子问题的解避免重复计算。
设矩阵链为 A₁, A₂, ..., Aₙ,其中 Aᵢ 的维度为 p[i-1] × p[i]。我们定义一个二维数组 m[i][j] 表示计算从第 i 个到第 j 个矩阵相乘所需的最小乘法次数。
状态转移方程如下:
m[i][j] = min{ m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j] } 其中 i ≤ k < j同时,为了记录最优分割点(用于后续构造括号方案),我们还需要一个数组 s[i][j] 保存使 m[i][j] 最小的 k 值。
下面是一个完整的 Java 实现,包含计算最小代价和打印最优括号化方案的功能:
public class MatrixChainMultiplication { // 计算最小乘法次数并记录分割点 public static int[][] matrixChainOrder(int[] p) { int n = p.length - 1; // 矩阵数量 int[][] m = new int[n + 1][n + 1]; int[][] s = new int[n + 1][n + 1]; // 初始化对角线为0(单个矩阵无需乘法) for (int i = 1; i <= n; i++) { m[i][i] = 0; } // l 是链的长度(从2开始) for (int l = 2; l <= n; l++) { for (int i = 1; i <= n - l + 1; i++) { int j = i + l - 1; m[i][j] = Integer.MAX_VALUE; for (int k = i; k < j; k++) { int cost = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; if (cost < m[i][j]) { m[i][j] = cost; s[i][j] = k; } } } } // 打印最优括号化方案 System.out.print("最优括号化方案: "); printOptimalParens(s, 1, n); System.out.println(); return m; } // 递归打印括号 public static void printOptimalParens(int[][] s, int i, int j) { if (i == j) { System.out.print("A" + i); } else { System.out.print("("); printOptimalParens(s, i, s[i][j]); printOptimalParens(s, s[i][j] + 1, j); System.out.print(")"); } } // 测试主函数 public static void main(String[] args) { // 示例:矩阵维度为 [30, 35, 15, 5, 10, 20] // 表示 A1:30×35, A2:35×15, A3:15×5, A4:5×10, A5:10×20 int[] p = {30, 35, 15, 5, 10, 20}; int[][] m = matrixChainOrder(p); System.out.println("最小乘法次数: " + m[1][p.length - 1]); }}以上代码运行后,会输出:
最优括号化方案: ((A1(A2A3))((A4A5)))最小乘法次数: 15125
这表示按照该括号方式计算,总共只需 15125 次标量乘法,远优于其他方案。
通过本教程,你已经掌握了:
这个问题不仅考察算法思维,也是面试中常见的动态规划题型。建议你动手敲一遍代码,加深理解!
掌握矩阵链乘法,你就离算法高手又近了一步!
本文由主机测评网于2025-12-06发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025123569.html