Skip to content

Commit fd6fbf8

Browse files
committed
feat: Add Matrix Chain Multiplication in C++
1 parent e316c46 commit fd6fbf8

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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 << "\nFor 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

Comments
 (0)