#include <iostream>
#include <vector>
#include <climits>
#include <string>
using namespace std;
// 动态规划计算矩阵连乘的最小乘法次数并输出乘法顺序
pair<int, string> matrixChainOrder(const vector<int>& dims) {
int n = dims.size() - 1; // 矩阵的个数
vector<vector<int>> dp(n, vector<int>(n, 0)); // dp[i][j]表示矩阵Ai到Aj之间的最小乘法次数
vector<vector<int>> split(n, vector<int>(n, 0)); // split[i][j]记录矩阵Ai到Aj最优分割点
vector<vector<string>> name(n, vector<string>(n)); // 存储矩阵名称或组合乘法顺序
// 初始化矩阵名称
char currentName = 'A';
for (int i = 0; i < n; ++i) {
name[i][i] = string(1, currentName++); // A, B, C, ...
}
// 枚举链长,从2开始到n
for (int len = 2; len <= n; ++len) {
for (int i = 0; i < n - len + 1; ++i) {
int j = i + len - 1; // 矩阵链的结束位置
dp[i][j] = INT_MAX; // 初始化为无穷大
// 通过分割不同的点来寻找最小的乘法次数
for (int k = i; k < j; ++k) {
int q = dp[i][k] + dp[k + 1][j] + dims[i] * dims[k + 1] * dims[j + 1];
if (q < dp[i][j]) {
dp[i][j] = q;
split[i][j] = k;
name[i][j] = "(" + name[i][k] + " x " + name[k + 1][j] + ")";
}
}
}
}
return { dp[0][n - 1], name[0][n - 1] }; // 返回最小的乘法次数和最优乘法顺序
}
int main() {
int numMatrices;
// 输入矩阵的个数
cout << "请输入矩阵的个数: ";
cin >> numMatrices;
vector<int> dims(numMatrices + 1); // 存储矩阵的维度数组P
// 输入维度数组P
cout << "请输入维度数组(长度为" << numMatrices + 1 << "):" << endl;
for (int i = 0; i <= numMatrices; ++i) {
cin >> dims[i];
}
// 计算最小的乘法次数和乘法顺序
pair<int, string> result = matrixChainOrder(dims);
// 输出最优连乘顺序和最小的矩阵连乘次数
cout << "最优的矩阵连乘顺序为: " << result.second << endl;
cout << "最小的矩阵连乘次数为: " << result.first << endl;
return 0;
}