/**
矩阵连乘法问题
(动态规划)
A1 A2 A3 A4
矩阵 m*n
5*4 4*3 3*6 6*2
合理的位置添加括号能使乘法次数减少
只有p[0]存储的是行的位置
1~n存储的分别是矩阵1~n的列的位置
因为他们的行就是前一个元素的值
p[0] = 5
p[1] = 4
p[2] = 3
p[3] = 6
p[4] = 2
*/
#include<stdio.h>
/**
参数 说明
n :表示多少个矩阵连乘
m[i][j] :存储的是 i~j矩阵连乘的次数
s[i][j]=k :存储的是 i~j中间从k位置加括号
*/
//这里我们就以4个矩阵为例
void MatrixChain(int *p,int n,int **m,int **s){
//将矩阵分成m[i][i]~m[i+1][j] ,m[i][i]肯定是0,一个矩阵不用乘次数都为0
for(int i=1;i<=n;i++)m[i][i] = 0;
//分别求1,2,3,4
//也就是求子问题,父问题会用到子问题的结果
//r代表 2~n个一划分
for(int r=2;r<=n;r++){
//分出几个一组许多需要分多少次?
/**
一个一划分:已经求过了m[i][i] = 0
两个一划分:(A1A2) A3A4
A1 (A2A3) A4
A1A2 (A3A4)
(需要3次)
三个一划分: (A1A2A3) A4
A1 (A2A3A4)
(需要两次)
*/
//n-r+1 每次划分需要的次数
for(int i=1;i<=n-r+1;i++){
int j = i+r-1; //i~j相乘,最后一个j的下标
//i~i i+1~j这样划分
m[i][j] = m[i][i] + m[i+1][j] + p[i-1]*p[i]*p[j];
//加括号位置为i
s[i][j] = i;
//加括号位置为k
for(int k=i+1;k<j;k++){
int t = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
if(t < m[i][j]){
m[i][j] = t;
s[i][j] = k;
}
}
}
}
}