1+ /* *
2+ * matrix_chain_multiplication.cpp
3+ * Implementation of the Matrix Chain Multiplication (MCM) problem.
4+ *
5+ * Description:
6+ * This program finds the most efficient way to multiply a chain of matrices.
7+ * The problem is not to perform the multiplications, but to decide the sequence
8+ * of parenthesizations. We use a Dynamic Programming approach, specifically the
9+ * Partition DP pattern.
10+ *
11+ * The state dp[i][j] represents the minimum number of scalar multiplications
12+ * needed to compute the product of matrices from index i to j.
13+ *
14+ * The state transition is:
15+ * dp[i][j] = min(dp[i][k] + dp[k+1][j] + dims[i-1]*dims[k]*dims[j])
16+ * for all k from i to j-1.
17+ *
18+ * Complexity Analysis:
19+ * - Time Complexity: O(n^3), where n is the number of matrices. Three nested loops are used.
20+ * - Space Complexity: O(n^2) for the DP table.
21+ */
22+ #include < iostream>
23+ #include < vector>
24+ #include < limits>
25+
26+ using namespace std ;
27+
28+ /* *
29+ * @brief Solves the Matrix Chain Multiplication problem using tabulation.
30+ * @param dims A vector where dims[i-1] and dims[i] are the dimensions of matrix i.
31+ * @return The minimum number of scalar multiplications.
32+ */
33+ int matrixChainOrder (const vector<int >& dims) {
34+ // There are n-1 matrices.
35+ int n = dims.size () - 1 ;
36+ if (n < 2 ) {
37+ return 0 ; // No multiplication needed if there's 0 or 1 matrix.
38+ }
39+
40+ // dp[i][j] = Minimum number of multiplications to compute matrix M[i]...M[j]
41+ // where M[i] has dimensions dims[i-1] x dims[i].
42+ vector<vector<int >> dp (n + 1 , vector<int >(n + 1 , 0 ));
43+
44+ // L is the chain length. It varies from 2 to n.
45+ for (int L = 2 ; L <= n; ++L) {
46+ // i is the starting matrix index.
47+ for (int i = 1 ; i <= n - L + 1 ; ++i) {
48+ // j is the ending matrix index.
49+ int j = i + L - 1 ;
50+ dp[i][j] = numeric_limits<int >::max ();
51+
52+ // k is the partition point.
53+ for (int k = i; k < j; ++k) {
54+ // Cost to multiply M[i]..M[k] and M[k+1]..M[j]
55+ // and then the final two resulting matrices.
56+ int cost = dp[i][k] + dp[k + 1 ][j] + dims[i - 1 ] * dims[k] * dims[j];
57+ if (cost < dp[i][j]) {
58+ dp[i][j] = cost;
59+ }
60+ }
61+ }
62+ }
63+ return dp[1 ][n];
64+ }
65+
66+ // Example usage and test cases
67+ int main () {
68+ // Example: We have 4 matrices with dimensions:
69+ // M1: 10x30, M2: 30x5, M3: 5x60, M4: 60x20
70+ // The dimensions array will be {10, 30, 5, 60, 20}
71+ vector<int > dims = {10 , 30 , 5 , 60 , 20 };
72+ cout << " The dimensions of the matrices are: " ;
73+ for (size_t i = 0 ; i < dims.size () -1 ; ++i) {
74+ cout << dims[i] << " x" << dims[i+1 ] << (i == dims.size () - 2 ? " " : " , " );
75+ }
76+ cout << endl;
77+
78+ int min_multiplications = matrixChainOrder (dims);
79+ cout << " Minimum number of scalar multiplications needed is: " << min_multiplications << endl; // Expected: 13500
80+
81+ vector<int > dims2 = {40 , 20 , 30 , 10 , 30 };
82+ cout << " \n For dimensions {40, 20, 30, 10, 30}:" << endl;
83+ cout << " Minimum number of scalar multiplications needed is: " << matrixChainOrder (dims2) << endl; // Expected: 26000
84+
85+ return 0 ;
86+ }
0 commit comments