#include<stdio.h>
#include<iostream>
#include<limits>
using namespace std;
const int Rows = 3;
const int Columns = 2;
int c[Rows][Rows];
const int N = 6;//矩阵个数
void MatrixMultiply(int a[Rows][Columns], int b[Columns][Rows]);
void MatrixChainOrder(int p[], int n, int m[][N], int s[][N]);
void PrintParens(int s[N][N],int i ,int j);
int main ()
{
int a[Rows][Columns] = {{1, 2}, {3, 4}, {5, 6}};
int b[Columns][Rows] = {{1, 2, 3}, {4, 5, 6}};
MatrixMultiply(a, b);
for(int i = 0; i < Rows; i++)
{
for(int j = 0; j < Rows; j++)
cout << c[i][j] << " ";
cout << endl;
}
int p[N + 1]={30,35,15,5,10,20,25};//记录6个矩阵的行和列,注意相邻矩阵的行和列是相同的
int m[N][N]={0};//存储第i个矩阵到第j个矩阵的计算代价(以乘法次数来表示)
int s[N][N]={0};//存储第i个矩阵到第j个矩阵的最小代价时的分为两部分的位置
MatrixChainOrder(p, N, m, s);
printf("\n最终加括号的形式为: ");
PrintParens(s, 0, N - 1);//计算从第1个矩阵到第6个矩阵的最优加括号的方法
printf("\n");
}
void PrintParens(int s[N][N],int i ,int j)
{
if(i==j)
printf("A%d",i);
else
{
printf("(");
PrintParens(s,i,s[i][j]);
PrintParens(s,s[i][j]+1,j);//递归调用
printf(")");
}
}
void MatrixMultiply(int a[Rows][Columns], int b[Columns][Rows])
{
for(int i = 0; i < Rows; i++)
{
for(int j = 0; j < Rows; j++)
{
c[i][j] = 0;
for(int k = 0; k < Columns; k++)
{
c[i][j] = c[i][j] + a[i][k] * b[k][j];
}
}
}
}
void MatrixChainOrder(int p[], int L, int m[][N], int s[][N])
{
int n = L;
int q = 0, j = 0;
//m[i, j]表示计算矩阵A(i, j)所需标量乘法次数的最小值
//则原问题的最优解 计算A(1...n)所需的最小代价就是m[1, n]
//递归定义m[i,j]如下 对于i=j的平凡问题 矩阵链只包含唯一的矩阵A(i,j)=Ai因此不需要做任何标量乘法运算
//因此对所有i=1,2,3...n, m[i,i]=0 若i<j则利用最优子结构来计算m[i,j]
//假设最优括号化方案的分割点在矩阵Ak到Ak+1之间 (i<=k<j)那么 m[i,j]就等于计算A(i...k)和A(k+1...j)的代价加上两者相乘的低价的最小值
//由于矩阵Ai的大小为pi-1*pi 因此Ai...k与Ak+1...j相乘的代价为
for(int i = 0; i < n; i++)
{
m[i][i] = 0;//0是长度为1的链的最小代价 即Ai...i因此只代表一个矩阵 谈不上最优
//因此m的对角线元素值均为0
}
for(int l = 2; l <= n; l++)//从计算m[i,i+1](l=2的最小计算代价)开始
{ //l=2的执行过程:m[1][2],m[2][3],m[3][4]...
//l=3的执行过程:m[1][3],....
for(int i = 0; i < n - l + 1; i++)
{
j = i + l - 1;
m[i][j] = 100000;//不会出现i=j的情况 因为j=i+l-1 -> 若是i=j则l=1但l是从2开始的
for(int k = i; k <= j - 1; k++)
{//q表示当前计算代价 p[i - 1] * p[k] * p[j]代表的是两部分矩阵的乘法代价 对于第i个矩阵来说 它的行数存储在p[i-1]中
q = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1];
if(q < m[i][j])
{
m[i][j] = q;
s[i][j] = k;
}
}
}
}
}