矩阵连乘问题(C++)

来源:互联网 发布:js搅拌机型号 编辑:程序博客网 时间:2024/05/01 08:05

Description

给定n个矩阵{A0,A1,…,An-1}, 其中Ai,i=0,…,n-1的维数为pi*pi+1,并且Ai与Ai+1是可乘的。考察这n个矩阵的连乘积A0A1…An-1,由于矩阵乘法满足结合律,所以计算矩阵的连乘可有许多不同的计算次序。矩阵连乘问题是确定计算矩阵连乘积的计算次序,使得按照这一次序计算矩阵连乘积,需要的“数乘”次数最少。Input第一行输入n的值,第二行输入n个矩阵的维数pi(i=0,…,n)。Output最少乘法次数。

Sample Input

6

30 35 15 5 10 20 25

Sample Output

15125

Source

矩阵连乘算法算是经典的动态规划算法的问题(Dynamic Programming)(明显的具有最优子结构重叠子问题的特点,证明略)。既然是动态规划问题,那很明显是用到了数组来存储子结构的解

我们这里主要用到两个数组,一个是p数组,这是一维数组,存储着矩阵的维数,因为相邻两边的矩阵维数默认相同,对于n个矩阵来说,只需n+1个空间即可存储。

还有一个是m数组,这是一个二维数组m,m[i][j]是表示第i个矩阵和第j个矩阵相乘的计算次数。那么m[i][i]理所当然就是0啦,因为是自己乘自己。

如果i不等于j的话,我们就来一个递归的操作:设一个中间值k,i<=k<j,则m[i][j]=min{m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1]}(因为这个值是不停地比较产生的,所以需要去所有情况的最小值)这样就形成了一个类似于上三角的矩阵来表示递推计算次序:

右上角的是最终我们需要求的值,即是m[0][n-1],代码实现如下:

#include <iostream>using namespace std;void Mchain(int *p,int m[][100],int n)//计算将m矩阵数字填满 {for(int r=2;r<=n;r++){for(int i=0;i<=n-r;i++){int j=i+r-1;m[i][j]=m[i][i]+m[i+1][j]+p[i]*p[i+1]*p[j+1];for(int k=i+1;k<j;k++){int t=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];if(t<m[i][j]){m[i][j]=t;}}}}}int main(){int n;int p[100],m[100][100];cin>>n;for(int i=0;i<=n;i++){cin>>p[i];}for(int i=0;i<n;i++){m[i][i]=0;//矩阵自身相乘计算次数为0 }Mchain(p,m,n);cout<<m[0][n-1]<<endl;return 0;}


0 0
原创粉丝点击