给定一系列矩阵,找到将这些矩阵相乘的最有效方法。问题实际上不是执行乘法,而是仅决定执行乘法的顺序。
因为矩阵乘法是关联的,所以我们有很多选择可以乘法矩阵链。换句话说,无论我们如何对产品加上括号,结果都是一样的。例如,如果我们有四个矩阵A,B,C和D,则将有:
(ABC)D = (AB)(CD) = A(BCD) = ....
但是,括号内乘积的顺序会影响计算乘积所需的简单算术运算的数量或效率。例如,假设A为10×30矩阵,B为30×5矩阵,C为5×60矩阵。然后,
(AB)C = (10×30×5) + (10×5×60) = 1500 + 3000 = 4500 operations
A(BC) = (30×5×60) + (10×30×60) = 9000 + 18000 = 27000 operations.
显然,第一个括号需要较少的操作。
给定表示矩阵链的数组p [],使第i个矩阵Ai的尺寸为p [i-1] xp [i]。我们需要编写一个函数MatrixChainOrder(),该函数应返回乘法链所需的最小乘法数。
Input: p[] = {40, 20, 30, 10, 30}
Output: 26000
There are 4 matrices of dimensions 40x20, 20x30, 30x10 and 10x30.
Let the input 4 matrices be A, B, C and D. The minimum number of
multiplications are obtained by putting parenthesis in following way
(A(BC))D --> 20*30*10 + 40*20*10 + 40*10*30
Input: p[] = {10, 20, 30, 40, 30}
Output: 30000
There are 4 matrices of dimensions 10x20, 20x30, 30x40 and 40x30.
Let the input 4 matrices be A, B, C and D. The minimum number of
multiplications are obtained by putting parenthesis in following way
((AB)C)D --> 10*20*30 + 10*30*40 + 10*40*30
Input: p[] = {10, 20, 30}
Output: 6000
There are only two matrices of dimensions 10x20 and 20x30. So there
is only one way to multiply the matrices, cost of which is 10*20*30
我们讨论了矩阵链乘法问题的O(n ^ 3)解。
注意:以下解决方案在许多情况下不起作用。例如:对于输入{2,40,2,40,5},正确答案是580,但是此方法返回720
还有另一种类似的方法可以解决此问题。更直观和递归的方法。
Assume there are following available method
minCost(M1, M2) -> returns min cost of multiplying matrices M1 and M2
Then, for any chained product of matrices like,
M1.M2.M3.M4…Mn
min cost of chain = min(minCost(M1, M2.M3…Mn), minCost(M1.M2..Mn-1, Mn))
Now we have two subchains (sub problems) :
M2.M3…Mn
M1.M2..Mn-1
C++
// CPP program to implement optimized matrix chain multiplication problem.
#include
using namespace std;
// Matrix Mi has dimension p[i-1] x p[i] for i = 1..n
int MatrixChainOrder(int p[], int n)
{
/* For simplicity of the program, one extra row and one extra column are allocated in
dp[][]. 0th row and 0th column of dp[][] are not used */
int dp[n][n];
/* dp[i, j] = Minimum number of scalar multiplications needed to compute the matrix M[i]M[i+1]...M[j]
= M[i..j] where dimension of M[i] is p[i-1] x p[i] */
// cost is zero when multiplying one matrix.
for (int i=1; i
Java
// Java program to implement optimized matrix chain multiplication problem.
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG{
// Matrix Mi has dimension p[i-1] x p[i] for i = 1..n
static int MatrixChainOrder(int p[], int n)
{
/* For simplicity of the program, one extra row and one extra column are
allocated in dp[][]. 0th row and 0th column of dp[][] are not used */
int [][]dp=new int[n][n];
/* dp[i, j] = Minimum number of scalar multiplications needed to compute the matrix M[i]M[i+1]...M[j]
= M[i..j] where dimension of M[i] is p[i-1] x p[i] */
// cost is zero when multiplying one matrix.
for (int i=1; i
Python3
# Python3 program to implement optimized
# matrix chain multiplication problem.
# Matrix Mi has dimension
# p[i-1] x p[i] for i = 1..n
def MatrixChainOrder(p, n):
# For simplicity of the program, one
# extra row and one extra column are
# allocated in dp[][]. 0th row and
# 0th column of dp[][] are not used
dp = [[0 for i in range(n)]
for i in range(n)]
# dp[i, j] = Minimum number of scalar
# multiplications needed to compute
# the matrix M[i]M[i+1]...M[j] = M[i..j]
# where dimension of M[i] is p[i-1] x p[i]
# cost is zero when multiplying one matrix.
for i in range(1, n):
dp[i][i] = 0
# Simply following above recursive formula.
for L in range(1, n - 1):
for i in range(n - L):
dp[i][i + L] = min(dp[i + 1][i + L] +
p[i - 1] * p[i] * p[i + L],
dp[i][i + L - 1] +
p[i - 1] * p[i + L - 1] * p[i + L])
return dp[1][n - 1]
# Driver code
arr = [10, 20, 30, 40, 30]
size = len(arr)
print("Minimum number of multiplications is",
MatrixChainOrder(arr, size))
# This code is contributed
# by sahishelangia
C#
// C# program to implement optimized
// matrix chain multiplication problem.
using System;
class GFG
{
// Matrix Mi has dimension
// p[i-1] x p[i] for i = 1..n
static int MatrixChainOrder(int []p, int n)
{
/* For simplicity of the program,
one extra row and one extra
column are allocated in dp[][].
0th row and 0th column of dp[][]
are not used */
int [,]dp = new int[n, n];
/* dp[i, j] = Minimum number of scalar
multiplications needed to compute
the matrix M[i]M[i+1]...M[j] = M[i..j]
where dimension of M[i] is p[i-1] x p[i] */
// cost is zero when multiplying
// one matrix.
for (int i = 1; i < n; i++)
dp[i, i] = 0;
// Simply following above
// recursive formula.
for (int L = 1; L < n - 1; L++)
for (int i = 1; i < n - L; i++)
dp[i, i + L] = Math.Min(dp[i + 1, i + L] +
p[i - 1] * p[i] * p[i + L],
dp[i, i + L - 1] + p[i - 1] *
p[i + L - 1] * p[i + L]);
return dp[1, n - 1];
}
// Driver code
public static void Main()
{
int []arr = {10, 20, 30, 40, 30} ;
int size = arr.Length;
Console.WriteLine("Minimum number of multiplications is " +
MatrixChainOrder(arr, size));
}
}
// This code is contributed by anuj_67
PHP
Minimum number of multiplications is 30000
感谢Rishi_Lazy提供上述优化的解决方案。
时间复杂度: O(n 2 )
以矩阵链乘法打印括号