動態(tài)規(guī)劃求解矩陣連乘的最優(yōu)時間復雜度
給定一系列矩陣
由于矩陣乘法要求兩個相乘矩陣的維度滿足:第一個矩陣的列數(shù)要與第二個矩陣的行數(shù)相同。所以我們只要用
給定一個矩陣序列
如果你不想看分析過程可以直接看后面的算法實現(xiàn)部分。
如果我們用
類似地,對于任意的正整數(shù)
而且我們還知道:
那么,如果我們用矩陣
利用動態(tài)規(guī)劃的思想解決矩陣序列連乘問題的算法本身的時間復雜度跟
第
第
第
第
第
第
第
第
第
第
所以計算時間復雜度為:
時間復雜度的推到請參考這個鏈接 https://en.wikipedia.org/wiki/Faulhaber%27s_formula
雖然算法時間復雜度為
完整的C++實現(xiàn)如下:
#include
#include
using namespace std;
// 尋找最優(yōu)時間復雜度 B,以及最優(yōu)劃分 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;
}
}
}
// 輸出最優(yōu)時間復雜度下矩陣的相乘順序
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
是為了更好的格式化輸出。