矩阵链乘法

对矩阵链加括号的方式会对乘积运算的代价产生巨大影响,现在使用动态规划来对矩阵链乘法问题进行求解。

矩阵链乘法问题可描述如下:给定n个矩阵的链<A1,A2,...,An>,矩阵Ai的规模为pi-1*pi(1 =< i =<n),求完全括号化方案,使得计算乘积A1A2…An所需标量乘法次数最少。

步骤1:最优括号化方案的结构特征

动态规划方法的第一步是寻找最优子结构,然后就可以利用这种子结构从子问题的最优解构造出原问题的最优解。现在给出本问题的最优子结构。假设AiAi+1…Aj的最优括号化方案的分割点在Ak和Ak+1之间。那么,继续对“前缀”子链AiAi+1…Ak进行括号化,我们应该直接采用独立求解它时所得的最优方案。对Ak+1Ak+2…Aj我们有相似的结论。

步骤2:一个递归求解方案

下面用子问题的最优解来递归地定义原问题最优解的代价。对矩阵链乘法问题,我们可以将所有1≤i≤j≤n确定AiAi+1…Aj的最小代价括号化方案作为子问题。令m[i][j]表示计算矩阵Ai..j所需要标量乘法次数的最小值,那么,原问题的最优解——计算A1..n所需的最低代价就是m[1][n]。递归求解公式如下所示:

步骤3:计算最优代价

实现代码如下所示:

void MATRIX_CHAIN_ORDER(int *p, int m[LEN][LEN], int s[LEN][LEN])
{
    //m[i,j]表示计算矩阵Ai.j所需要的标量乘法次数的最小值
    //s[i,j]记录分割点
    int i, j, k, l;//l表示矩阵链的长度
    int q;//保存最小乘法运算次数
    for(i = 0; i < LEN; i++)//只有一个矩阵,乘法运算次数为0
        m[i][i] = 0;
    for(l = 2; l < LEN; l++)
    {
        for(i = 1; i < LEN-l+1; i++)
        {
            j = i+l-1;
            m[i][j] = MAX;
            for(k = i; k < j; k++)
            {
                q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
                if(q < m[i][j])
                {
                    m[i][j] = q;
                    s[i][j] = k;
                }
            }
        }
    }
}

假设有如下的矩阵链:

则构成如下的矩阵规模序列:

根据动态规划,可求得如下的两个矩阵,m[i][j]表示计算矩阵Ai..j所需要标量乘法次数的最小值,而s[i][j]表示矩阵Ai..j所需要标量乘法次数的最小值的切割点:

如m[1][4] = 405,表示矩阵链A1A2A3A4的最小标量乘法次数为405次,s[1][4] = 2,表示最小标量乘法的切割法的切割点为2,即变为(A1A2)(A3A4)。这里要注意一点的是:在求m[1][4]时,其所有子问题都已求出。

结果打印函数:

void PRINT_OPTIMAL_PARENS(int s[LEN][LEN], int i, int j)
{
    if(i == j)
        cout<<"A"<<i;
    else
    {
        cout<<"(";
        PRINT_OPTIMAL_PARENS(s,i,s[i][j]);
        PRINT_OPTIMAL_PARENS(s,s[i][j]+1,j);
        cout<<")";
    }
}

最后求得的结果为:

矩阵链乘法

时间: 2024-10-15 06:08:28

矩阵链乘法的相关文章

算法13---动态规划矩阵链乘法

算法13---动态规划矩阵链乘法 矩阵链乘法是动态规划里面使用到的一个例子 1 两个矩阵的计算 那么对于一个矩阵的乘法,首先如果是两个矩阵的乘法,那么如何实现呢? 注意到我们使用二维数组表示矩阵,但是二维数组不能作为函数的返回值.具体实现如下 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <math.h> 4 5 #define a_rows 3 6 #define a_columns 4 7 #define

动态规划-矩阵链乘法

问题描述: 给定由n个要相乘的矩阵构成的序列(链)<A1,A2,...,An>,要计算乘积A1A2...An,可以将两个矩阵相乘的标准算法作为一个子程序,通过加括号确定计算的顺序(对同一矩阵链,不同的计算顺序所需要的计算次数大不相同). 目标问题:给定n个矩阵构成的矩阵链<A1,A2,...,An>,其中,i=1,2,...,n,矩阵Ai的维数为pi-1×pi,对乘积A1A2...An以一种最小计算次数加全部括号. 穷尽搜索: 令P(n)表示一串n个矩阵可能的加全部方案数.当n=1

Algorithm --&gt; 矩阵链乘法

动态规划--矩阵链乘法 1.矩阵乘法 Note:只有当矩阵A的列数与矩阵B的行数相等时A×B才有意义.一个m×r的矩阵A左乘一个r×n的矩阵B,会得到一个m×n的矩阵C. #include <iostream> using namespace std; #define A_ROWS 3 #define A_COLUMNS 2 #define B_ROWS 2 #define B_COLUMNS 3 void matrix_multiply(int A[A_ROWS][A_COLUMNS],in

矩阵链乘法(动态规划)

一 题意描述: 给定由n个要相乘的矩阵构成的序列(链)<A1,A2,A3,····An>.由于矩阵满足结合律(加括号方式表示结合方式),不同的计算方式导致的求出最终计算结果的代价相异,有的花的时间很少,有的方式所花时间很多,那么下面的任务就是求出算出结果所需要的最少时间及一个最优解. 二 思路分析: 设p(n)表示一串n个矩阵可能的加全部括号方案数.当n=1时,只有一个矩阵,此时p(1)=1.当n>=2时,一个加全部括号的矩阵乘积等于两个加全部括号的子矩阵乘积的乘积,而且这两个子乘积之间

[CLRS][CH 15.2] 动态规划之矩阵链乘法

摘要 整理了矩阵链乘法的动态规划思路. 题目 给定n个要相乘的矩阵构成的序列<A1, A2, ... , An>,其中 i=1, 2, ..., n,矩阵 Ai 的维数为pi-1*pi.计算乘积 A1A2...An 的最小代价的矩阵相乘循序. 补充:矩阵乘法满足结合律,例如,乘积 A1A2A3A4 共有五种不同加括号结合形式.不同的结合形式极大的影响运算效率.当且仅当矩阵A和B相容(A.列 = B.行)时,才可以计算矩阵乘法.例如:矩阵A为p*q, 矩阵B为q*r,则相乘后得到的矩阵C为p*r

算法导论--动态规划(矩阵链乘法)

矩阵链乘法问题 给定一个n个矩阵的序列?A1,A2,A3...An?,我们要计算他们的乘积:A1A2A3...An.因为矩阵乘法满足结合律,加括号不会影响结果.可是不同的加括号方法.算法复杂度有非常大的区别: 考虑矩阵链:?A1,A2,A3?.三个矩阵规模分别为10×100.100×5.5×50 假设按((A1A2)A3)方式,须要做10?100?5=5000次,再与A3相乘,又须要10?5?50=2500,共须要7500次运算: 假设按(A1(A2A3))方式计算.共须要100?5?50+10

【算法导论】动态规划之“矩阵链乘法”问题

上一篇里,介绍了动态规划的"钢管切割"问题,这一次来看看"矩阵链乘法".所谓矩阵链乘法就是一个或一个以上的矩阵连续相乘,这里主要关注的是乘法的次数. 一.概述 以两个矩阵相乘为例,A1*A2,A1和A2为两个矩阵,假设A1的行列数是p*q,A2的行列数是q*r.注意这里由于是A1乘以A2,所以A1的列数要等于A2的行数,否则无法做矩阵乘法,满足上述条件的矩阵,我们称之为"相容"的.那么对于A1*A2而言,我们需要分别执行p*r次对应A1的行元素乘

[动态规划] 矩阵链乘法问题

什么是矩阵链乘法(Matrix Chain Multiplication) 矩阵链乘法问题是指给定一串矩阵序列M?M2..Mn,求至少需要进行多少次乘法运算才能求得结果 比如对于这个M?M?M?的矩阵链, 我们可以先计算M?M?然后结果乘以M?,也可以M?M?先算,然后乘以M?,为了表达方便,可以用括号表示计算顺序. 矩阵链M?M?M?有两种计算顺序:((M?M?)M?)和(M?(M?M?)). 那么不同计算顺序有什么区别? 对于((M?M?)M?): 对于(M?(M?M?)):  我们要做的就

MCM(矩阵链乘法)

这是<算法导论>动态规划中的一个问题.问题简述如下:我们在求解矩阵相乘时通常会有一个最优括号方案来对矩阵进行顺序相乘,这样会减少大量的计算时间. 我们知道矩阵A*B相乘,只能是当矩阵A的列数等于矩阵B的行数时才能进行相乘,且假设A·B = C,A为p×q规模的矩阵,B为q×r的矩阵,则乘积C的规模为p×r的矩阵.计算A·B所需的时间由乘法次数决定,即pqr. 例如:有三个矩阵的规模分别为:A = 10×100,B = 100×5,C = 5×50.如果按顺序(AB)C计算,则需要10×100×