Open In App

Matrix Chain Multiplication (A O(N^2) Solution)

Last Updated : 27 Jan, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array arr[] of size n, which represents the chain of matrices such that the ith matrix Ai is of dimension arr[i-1] x arr[i]. The task is to find the minimum number of multiplications needed to multiply the chain. 

Example:

Input: arr[] = [40, 20, 30, 10, 30]
Output: 26000  
Explanation: 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: arr[] = [10, 20, 30, 40, 30]
Output: 30000 
Explanation: 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: arr[] = {10, 20, 30}
Output: 6000  
Explanation: 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

Here are some more illustrations of the problem statement: We have many options to multiply a chain of matrices because matrix multiplication is associative. In other words, no matter how we parenthesize the product, the result will be the same.
If we had four matrices A, B, C, and D, we would have: 

    (ABC)D = (AB)(CD) = A(BCD) = ....

However, the order in which we parenthesize the product affects the number of simple arithmetic operations needed to compute the product or the efficiency.

For example: Suppose A is a 10 × 30 matrix, B is a 30 × 5 matrix, and C is a 5 × 60 matrix. Then, 

(AB)C = (10×30×5) + (10×5×60) = 1500 + 3000 = 4500 operations
A(BC) = (30×5×60) + (10×30×60) = 9000 + 18000 = 27000 operations.

Clearly, the first arrangement requires less number of operations.

We have discussed a O(n^3) solution for Matrix Chain Multiplication Problem

Note: Below solution does not work for many cases. For example: for input {2, 40, 2, 40, 5}, the correct answer is 580 but this method returns 720 

There is another similar approach to solving this problem. More intuitive and recursive approach.

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

Implementation:

C++
// CPP program to perform matrix 
// chain multiplication
#include<bits/stdc++.h>
using namespace std;

int matrixMultiplication(vector<int> &arr) {
    int n = arr.size();

    // create dp to store results
    vector<vector<int>> dp(n, vector<int>(n));

    // dp[i, j] = Minimum number of scalar multiplications 
    // needed to compute the matrix M[i]M[i+1]...M[j] 
    for (int i=1; i<n; i++)
        dp[i][i] = 0;
    for (int j=1; j<n-1; j++) 
        for (int i=1; i<n-j; i++)     
            dp[i][i+j] = min(dp[i+1][i+j] + arr[i-1]*arr[i]*arr[i+j],
                        dp[i][i+j-1] + arr[i-1]*arr[i+j-1]*arr[i+j]);     
    
    return dp[1][n-1];
}

int main() {

    vector<int> arr = {10, 20, 30, 40, 30};
    cout<< matrixMultiplication(arr);
    return 0;
}
Java
// Java program to perform matrix 
// chain multiplication
import java.util.*;

class GfG {

    static int matrixMultiplication(List<Integer> arr) {
        int n = arr.size();

        // create dp to store results
        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] 
        for (int i = 1; i < n; i++)
            dp[i][i] = 0;
        for (int j = 1; j < n - 1; j++) 
            for (int i = 1; i < n - j; i++)     
                dp[i][i + j] = 
              	Math.min(dp[i + 1][i + j] + arr.get(i - 1) * arr.get(i) * arr.get(i + j),
                dp[i][i + j - 1] + arr.get(i - 1) * arr.get(i + j - 1) * arr.get(i + j));     

        return dp[1][n - 1];
    }

    public static void main(String[] args) {

        List<Integer> arr = Arrays.asList(10, 20, 30, 40, 30);
        System.out.println(matrixMultiplication(arr));
    }
}
Python
# Python program to perform matrix 
# chain multiplication

def matrixMultiplication(arr):
    n = len(arr)

    # create dp to store results
    dp = [[0] * n for _ in range(n)]

    # dp[i, j] = Minimum number of scalar multiplications 
    # needed to compute the matrix M[i]M[i+1]...M[j] 
    for i in range(1, n):
        dp[i][i] = 0
    for j in range(1, n - 1):
        for i in range(1, n - j):
            dp[i][i + j] = min(dp[i + 1][i + j] + arr[i - 1] * arr[i] * arr[i + j],
                          dp[i][i + j - 1] + arr[i - 1] * arr[i + j - 1] * arr[i + j])

    return dp[1][n - 1]

if __name__ == "__main__":

    arr = [10, 20, 30, 40, 30]
    print(matrixMultiplication(arr))
C#
// C# program to perform matrix 
// chain multiplication
using System;
using System.Collections.Generic;

class GfG {

    static int MatrixMultiplication(List<int> arr) {
        int n = arr.Count;

        // create dp to store results
        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] 
        for (int i = 1; i < n; i++)
            dp[i, i] = 0;
        for (int j = 1; j < n - 1; j++) 
            for (int i = 1; i < n - j; i++)     
                dp[i, i + j] = Math.Min(dp[i + 1, i + j] + arr[i - 1] * arr[i] * arr[i + j],
                dp[i, i + j - 1] + arr[i - 1] * arr[i + j - 1] * arr[i + j]);     

        return dp[1, n - 1];
    }

    static void Main(string[] args) {

        List<int> arr = new List<int> {10, 20, 30, 40, 30};
        Console.WriteLine(MatrixMultiplication(arr));
    }
}
JavaScript
// JavaScript program to perform matrix 
// chain multiplication

function matrixMultiplication(arr) {
    let n = arr.length;

    // create dp to store results
    let dp = Array.from({ length: n }, () => Array(n).fill(0));

    // dp[i, j] = Minimum number of scalar multiplications 
    // needed to compute the matrix M[i]M[i+1]...M[j] 
    for (let i = 1; i < n; i++)
        dp[i][i] = 0;
    for (let j = 1; j < n - 1; j++) 
        for (let i = 1; i < n - j; i++)     
            dp[i][i + j] = Math.min(dp[i + 1][i + j] + arr[i - 1] * arr[i] * arr[i + j],
                        dp[i][i + j - 1] + arr[i - 1] * arr[i + j - 1] * arr[i + j]);     

    return dp[1][n - 1];
}

const arr = [10, 20, 30, 40, 30];
console.log(matrixMultiplication(arr));

Output
30000

Time Complexity: O(n2)  due to the two nested for loops used in "matrixMultiplication" function.
Auxiliary Space: O(n2) for the dp vector.

Printing Brackets in Matrix Chain Multiplication


Next Article
Article Tags :
Practice Tags :

Similar Reads