动态规划求解矩阵连乘的最优时间复杂度
扫描二维码
随时随地手机看文章
给定一系列矩阵
由于矩阵乘法要求两个相乘矩阵的维度满足:第一个矩阵的列数要与第二个矩阵的行数相同。所以我们只要用
给定一个矩阵序列
如果你不想看分析过程可以直接看后面的算法实现部分。
如果我们用
类似地,对于任意的正整数
而且我们还知道:
那么,如果我们用矩阵
利用动态规划的思想解决矩阵序列连乘问题的算法本身的时间复杂度跟
第
第
第
第
第
第
第
第
第
第
所以计算时间复杂度为:
时间复杂度的推到请参考这个链接 https://en.wikipedia.org/wiki/Faulhaber%27s_formula
虽然算法时间复杂度为
完整的C++实现如下:
#include
#include
using namespace std;
// 寻找最优时间复杂度 B,以及最优划分 K
void find_best_complexity(vector &B, vector &K, const int *d, int N){
B.resize(N*N);
K.resize(N*N);
for (int i = 0; i < N; i++){
B[i*N + i] = 0;
}
for (int v = 1; v < N; v++){
for (int u = v - 1; u > -1; u--){
int best_cmp = INT_MAX;
int best_k;
for (int k = u; k < v; k++){
int current_cmp = d[u] * d[k + 1] * d[v + 1] + B[u*N + k] + B[(k+1)*N + (v)];
if (current_cmp < best_cmp){
best_cmp = current_cmp;
best_k = k;
}
}
K[u*N + v] = best_k;
B[u*N + v] = best_cmp;
}
}
}
// 输出最优时间复杂度下矩阵的相乘顺序
void print_uv(int u, int v, vector &K, int &N){
if (u==v){
return;
}
int k = K[u*N+v];
print_uv(u, k, K, N);
print_uv(k + 1, v, K, N);
printf("%4d ", u);
printf("%4d ", k);
printf("%4d n", v);
}
// 举个例子
int main(int argc, char** argv){
int d[] = {1, 2, 3, 1, 5};
int N = (sizeof(d) / sizeof(d[0])) - 1;
vector B;
vector K;
find_best_complexity(B, K, d, N);
printf("###############################################################n");
printf("# Bn");
for (int u = 0; u < N; u++){
for (int v = 0; v < N; v++){
if (v < u){
printf("%4d ", -1);
}
else{
printf("%4d ", B[u*N + v]);
}
}
printf("n");
}
printf("###############################################################n");
printf("# Kn");
for (int u = 0; u < N; u++){
for (int v = 0; v < N; v++){
if (v < u){
printf("%4d ", -1);
}
else{
printf("%4d ", K[u*N + v]);
}
}
printf("n");
}
printf("###############################################################n");
printf("# ordern");
print_uv(0, N - 1, K, N);
return EXIT_SUCCESS;
}
上述代码用printf
是为了更好的格式化输出。