设从矩阵Ai 到 Aj 的矩阵序列为 A[i:j] , m[][] 存放最小乘法次数 ,自底向上求解求解 , 即从子链长度为1 逐步求解子链长度为n的解
当 i==j 时 , 不需要乘 , m[i][i] = 0
- 自底向上求解问题的解 ,
- 当子链长度为1的时候无需求解 , 及m[i][i] = 0
- 自底向上求解问题的解 ,
当i != j时候, 需要根据子问题的解来计算当前解
- m[i:j] = MIN{ m[i:k] +m[k+1] + ppp| k∈[i,j) }
- 尝试当前子链A[i:j]的所有断点(遍历) , 获得当前问题的最优解
- m[i:k] , 该子链长度小于m[i:j] 的长度 , 所以此时一定已经存在m[i:k]最优解
- m[k+1:j] , 同上当前就是最优解
- m[i:j] = MIN{ m[i:k] +m[k+1] + ppp| k∈[i,j) }
/*
矩阵连乘问题-动态规划
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//矩阵最大行/列 数
const int MAXSIZE = 101;
//矩阵最小的行/列 数
const int MINSIZE = 2;
//存放最优问题的断点
int s[MAXSIZE][MAXSIZE];
//存放子问题结果
int m[MAXSIZE][MAXSIZE];
//最多的矩阵的个数+1
const int MNUM = 3;
//存放可连乘矩阵的所有行列下标 , 由于 上一个矩阵的列等于下一个矩阵的行数
//故第n个矩阵的 行数为p[n-1] 列数为p[n]
int p[MNUM+1];
int tt = 0;
//输出问题解 可以省略最高维度的大小
void printres(int l, int r, int s[][MAXSIZE],int flag) {
if (l == r) {
printf("%d:%d", p[l - 1], p[l]);
return;
}
//printf("%d %d\n", l, r);
//system("pause");
if (flag) {
printf("(");
printres(l, s[l][r], s,0);
printf(")(");
printres(s[l][r] + 1, r, s,0);
printf(")");
}
else {
printf("[");
printres(l, s[l][r], s,1);
printf("][");
printres(s[l][r] + 1, r, s,1);
printf("]");
}
}
//动归解决问题
void solve() {
//A[i][i] 的乘法次数为0
for (int i = 1; i <= MNUM; i++) {
m[i][i] = 0;
}
//矩阵连乘子链的长度从2增长
for (int r = 2; r <= MNUM; r++) {
//i为r长度子链的起始下标
for (int i = 1; i <= MNUM - r + 1;i++) {
//j为r长度子链的尾下标
int j = i + r - 1;
//k ∈[i:j)
//先计算k = i 时的计算次数
m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];
s[i][j] = i;
for (int k = i + 1; k < j; k++) {
int temp = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (temp < m[i][j]) {
s[i][j] = k;
m[i][j] = temp;
}
}
}
}
}
int main()
{
while (1)
{
srand(time(NULL));
for (int i = 0; i <= MNUM; i++) {
//确定每个矩阵的行列数
p[i] = (rand() % (MAXSIZE - MINSIZE))+MINSIZE;
printf("%d ", p[i]);
}
printf("\n");
/*
p[0] = 10;
p[1] = 100;
p[2] = 5;
p[3] = 50;
for (int i = 0; i <= MNUM; i++) {
printf("%d ", p[i]);
}
printf("\n");
*/
solve();
printres(1, MNUM, s,1);
printf("最小乘法次数为 : %d\n", m[1][MNUM]);
system("pause");
}
return 0;
}
/*
p[0] - p[3] = 10 100 5 50
*/