矩阵连乘

来源:互联网 发布:js如何创建数组 编辑:程序博客网 时间:2024/05/16 17:08

一、矩阵连乘算法基本思想

矩阵连乘是基于动态规划的问题。面对ABCDEF...这么多矩阵连乘,让你在其中添加括号使得这些矩阵所做的乘法次数最少。面对这么大的一个问题,我们肯定无从下手。那么如果给你两个矩阵,你是不是又会骂,傻X都会呢?是的,既然解决不了这么大的问题,我们可以从两个矩阵开始,也就是原问题的最小子问题。两个矩阵相差,不能讨论所谓的最小乘法次数,因为情况只有一种,但是它记录了两个矩阵直接的乘法次数。接下来我们面对的是三个矩阵相乘ABC,三个矩阵相乘最后的步骤肯定是2个矩阵相乘的结果和剩下的那个矩阵相乘。那么要想得到三个矩阵连乘最小值则必须是min((AB)*C的乘法次数,A*(BC)的乘法次数),三个矩阵也很容易,那么四个呢?ABCD,如果要想得到四个矩阵相乘必须是min(ABC这三个矩阵相乘的乘法次数的最小值*D   ,  A* (BCD)这矩阵乘法次数的最小值 ),而ABC,BCD相乘乘法次数的最小值都是可以由上一步得到的,这些小规模问题的解可以用数组记录,以后用到就可以直接取得答案了。这样我们对于一个庞大的问题就可以轻而易举的用程序解决了。

二、矩阵连乘的数据结构

m[i][j]二维数组:表示从第i个矩阵连乘到第j个矩阵的最小乘法次数;

s[i][j]二维数组:表示从第i个矩阵连乘到第j个矩阵的最小乘法次数情况的时候,最后一次两个子矩阵相乘的分割点。

p[i]一位数组:表示矩阵i的行数,由于是可乘矩阵,那么p[i+1],就表示矩阵i的列数。

三、矩阵连乘表过程图解


四、算法源代码

#include<cstdio>#define MAXN 100int m[MAXN][MAXN];  //矩阵Ai*Ai+1*...*Aj的最少乘法次数int p[MAXN];        //代表矩阵Ai的行数int s[MAXN][MAXN];  //矩阵Ai*Ai+1*...*Aj的最少乘法次数的int n;              //矩阵个数void add_bracket(int i ,int j); //切分括号int main(){    printf("请输入矩阵个数\n");    scanf("%d",&n);    printf("请输入每个矩阵的行数\n");    for(int i=1;i<=n;i++)        scanf("%d",p+i);    printf("请输入最后一个矩阵的列数\n");    scanf("%d",p+n+1);    //自己不用和自己相乘,当然为0次    for(int i=1;i<=n;i++)        m[i][i] = 0;    //子问题规模,n个矩阵连乘    for(int r=2;r<=n;r++)    {        //子问题起点        for(int i=1;i<=n-r+1;i++)        {            int j = i+r-1;  //子问题终点            m[i][j] = m[i+1][j] + p[i]*p[i+1]*p[j+1];  //这里p[i]表示Ai矩阵的行数,p[i+1]表示矩阵的Ai+1的行数,p[j+1]表示Aj的列数            s[i][j] = i;                                //初始化分割点为矩阵Ai,即Ai*(Ai+1 * Ai+2 * .....Aj)            for(int k=i+1;k<=j-1;k++){                int t = m[i][k] + m[k+1][j] + p[i]*p[k+1]*p[j+1];        //这里p[i]表示Ai矩阵的行数,p[k+1]表示矩阵的Ak+1的行数,p[j+1]表示Aj的列数                if(t<m[i][j])                {                    m[i][j] = t;    //更新最小值                    s[i][j] = k;    //记录分割点                }            }        }    }    printf("最小乘法数为:%d\n",m[1][n]);    printf("括号添加方式为:\n");    add_bracket(1,n);}void add_bracket(int i,int j){    if(i==j)        return;    int a = s[i][j];    printf("Multiply A %d,%d and A %d, %d\n",i,a,a+1,j);    add_bracket(i,a);    add_bracket(a+1,j);}





0 0
原创粉丝点击