一.题目描述
输入:n个矩阵A1,A2,…,An,其中Ai的维数为pi-1×pi
Ai 和Ai+1是可乘的
输出:连乘积A1A2A3…An
优化目标:最小计算代价(最优的计算次序)
二.思路描述
1.输入分析
n个矩阵,输入他们的阶数,因为矩阵可以连乘,所以相邻矩阵的行数和列数相同,输入的时候相邻矩阵的行数和阶数只需要输入一个。
举例说明:
比如有三个矩阵A1(2*3) A2(3*4) A3(4*3),它们是可以连乘的,此时输入只需要输入 2 3 4 3即可;
2.输出分析
解决了输入的问题,接下来考虑算法的输出问题,题目要求输出最小计算代价,那么我们首先要考虑的问题就是什么叫做最小计算代价,这里我举例说明。
依旧以这三个数组为例:
A1(2*3) A2(3*4) A3(4*3)
根据矩阵的乘法可以知道,矩阵和矩阵相乘,实际上是矩阵里面的数字相乘,
并且A1*A2*A3=(A1*A2)*A3=A1*(A2*A3)
可以发现矩阵的乘法运算满足结合律,那么我们可以明白:
不同的计算代价对应于不同的结合律
这里我们直接计算说明
(A1*A2)*A3
它的计算次数为
2*3*4+2*4*3=48次;
A1*(A2*A3)
它的计算次数为
3*4*3+2*3*3=54次
很显然48 为该矩阵连乘的最小次数;
3.核心算法分析
我们进一步推广,有一串可以连乘的矩阵;
A1 A2 A3 A4...........An;
则对应的边有数组C1 C2 C3 C4 C5 ......Cn+1
为了方便表达,我们设B[i,j]为从矩阵A[i]到A[j]连乘所需要的次数;
进而我们通过构建可以得出动态规划的循环式
B[i,j]=B[i,k]+B[k+1,j]+C[i]*C[k]*C[j];
我们可以通过循环,来不断的确定所有的B[i,j]的值,进而求得最优值;
4.形象演示
我们通过表格的形式详细讲解动态规划的过程.
我们假设表格代表B[i,j];
1. 初始化
显然我们可知
i<=j
所以下半部分永远为0;
且当i=j时,B[i,j]=0;
红色代表未确定,绿色代表以确定,蓝色代表正在确定中。
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
那么我们依照算法
B[i,j]=B[i,k]+B[k+1,j]+C[i]*C[k]*C[j];、
可以发现,我们可以向右上方向逐层递进,最后得出结果;
这里我们可以计算蓝色区域的结果,最后一次循序渐进;
0 | x1 | 0 | 0 | 0 | 0 |
0 | 0 | x2 | 0 | 0 | 0 |
0 | 0 | 0 | x3 | 0 | 0 |
0 | 0 | 0 | 0 | x4 | 0 |
0 | 0 | 0 | 0 | 0 | x5 |
0 | 0 | 0 | 0 | 0 | 0 |
4.循环附加条件
举例说明
B[i,j]可能有多种计算方法导致不同的计算结果,用动态规划的方法,当出现新的B[i,j]时,我们需要进行比较并及时更新。
三.源代码
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int A[n-1][n-1];//代表从第i个矩阵到第j个矩阵所需要的计算次数,
int code[n];//矩阵依次的行列数
for(int i=0;i<n;i++)
{
cin>>code[i];//输入所有矩阵的行和列,相邻的只需要写一个
}
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-1;j++)
{
A[i][j]=0;
}
}
for(int r=0;r<n-1;r++)//注意循环的顺序,循序渐进 i为两个矩阵之间相差的矩阵数量
{
for(int i=0;i<n-2;i++)
{
int j=i+r+1;
if(A[i][j]==0)
{
A[i][j]=A[i][i]+A[i+1][j]+code[i]*code[i+1]*code[j+1];//,前后的矩阵所需要的计算次数,以及连接这两个大型矩阵所需要的次数
//说明从第i个矩阵到第j个矩阵所断开的地方
}
for(int k=i;k<=j;k++)
{
int min=A[i][k]+A[k+1][j]+code[i]*code[k+1]*code[j+1];
if(min<A[i][j])
{
A[i][j]=min;
}
}
}
}
cout<<A[0][n-2];
return 0;
}
四 .测试数据
无
五.遇到的问题及解决方法
动态规划的实现主要需要避免数据溢出的情况出现,因此要巧妙设计循环步骤。