From fd6fbf8cc27fa5c3ad903c89e485755153a76c1f Mon Sep 17 00:00:00 2001 From: parrth20 Date: Fri, 3 Oct 2025 23:07:25 +0530 Subject: [PATCH] feat: Add Matrix Chain Multiplication in C++ --- CPP/dynamic_programming/Matrix_chain_mul.cpp | 86 ++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 CPP/dynamic_programming/Matrix_chain_mul.cpp diff --git a/CPP/dynamic_programming/Matrix_chain_mul.cpp b/CPP/dynamic_programming/Matrix_chain_mul.cpp new file mode 100644 index 00000000..7f4246a5 --- /dev/null +++ b/CPP/dynamic_programming/Matrix_chain_mul.cpp @@ -0,0 +1,86 @@ +/** + * matrix_chain_multiplication.cpp + * Implementation of the Matrix Chain Multiplication (MCM) problem. + * + * Description: + * This program finds the most efficient way to multiply a chain of matrices. + * The problem is not to perform the multiplications, but to decide the sequence + * of parenthesizations. We use a Dynamic Programming approach, specifically the + * Partition DP pattern. + * + * The state dp[i][j] represents the minimum number of scalar multiplications + * needed to compute the product of matrices from index i to j. + * + * The state transition is: + * dp[i][j] = min(dp[i][k] + dp[k+1][j] + dims[i-1]*dims[k]*dims[j]) + * for all k from i to j-1. + * + * Complexity Analysis: + * - Time Complexity: O(n^3), where n is the number of matrices. Three nested loops are used. + * - Space Complexity: O(n^2) for the DP table. + */ +#include +#include +#include + +using namespace std; + +/** + * @brief Solves the Matrix Chain Multiplication problem using tabulation. + * @param dims A vector where dims[i-1] and dims[i] are the dimensions of matrix i. + * @return The minimum number of scalar multiplications. + */ +int matrixChainOrder(const vector& dims) { + // There are n-1 matrices. + int n = dims.size() - 1; + if (n < 2) { + return 0; // No multiplication needed if there's 0 or 1 matrix. + } + + // dp[i][j] = Minimum number of multiplications to compute matrix M[i]...M[j] + // where M[i] has dimensions dims[i-1] x dims[i]. + vector> dp(n + 1, vector(n + 1, 0)); + + // L is the chain length. It varies from 2 to n. + for (int L = 2; L <= n; ++L) { + // i is the starting matrix index. + for (int i = 1; i <= n - L + 1; ++i) { + // j is the ending matrix index. + int j = i + L - 1; + dp[i][j] = numeric_limits::max(); + + // k is the partition point. + for (int k = i; k < j; ++k) { + // Cost to multiply M[i]..M[k] and M[k+1]..M[j] + // and then the final two resulting matrices. + int cost = dp[i][k] + dp[k + 1][j] + dims[i - 1] * dims[k] * dims[j]; + if (cost < dp[i][j]) { + dp[i][j] = cost; + } + } + } + } + return dp[1][n]; +} + +// Example usage and test cases +int main() { + // Example: We have 4 matrices with dimensions: + // M1: 10x30, M2: 30x5, M3: 5x60, M4: 60x20 + // The dimensions array will be {10, 30, 5, 60, 20} + vector dims = {10, 30, 5, 60, 20}; + cout << "The dimensions of the matrices are: "; + for(size_t i = 0; i < dims.size() -1; ++i) { + cout << dims[i] << "x" << dims[i+1] << (i == dims.size() - 2 ? "" : ", "); + } + cout << endl; + + int min_multiplications = matrixChainOrder(dims); + cout << "Minimum number of scalar multiplications needed is: " << min_multiplications << endl; // Expected: 13500 + + vector dims2 = {40, 20, 30, 10, 30}; + cout << "\nFor dimensions {40, 20, 30, 10, 30}:" << endl; + cout << "Minimum number of scalar multiplications needed is: " << matrixChainOrder(dims2) << endl; // Expected: 26000 + + return 0; +} \ No newline at end of file