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

矩阵链乘法问题

给定一个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?100?50=75000次标量乘法,具有10倍的区别。

可见一个好的加括号方式,对计算效率有非常大影响。

为了得到所需乘法次数最少的方案,须要计算全部种方案的代价。

对一个n个矩阵的链,令P(n) 表示可供选择的括号化方案的数量。

全然括号化方案的矩阵乘积能够描写叙述为两个全然括号化的部分相乘的形式,

P(n)=1 , n=1

P(n)=∑n?1k=1P(k)P(n?k), n≥2

k为切割点,即第k个矩阵和第k+1个矩阵之间

能够看出括号化方案的数量与n呈指数关系Ω(2n)。若採用暴力搜索比較全部括号化方案的代价。效率非常差!

动态规划

1.最优括号化方案的结构特征

因为要求得矩阵链?Ai,Ai+1,Ai+2...Aj?的最优括号化方案,我们能够将问题划分为两个子问题?Ai,Ai+1...Ak?和?Ak+1,Ak+2...Aj?的最优括号化方案的组合,这也是能够採用动态规划的一个重要标示。即一个大的问题的解是其子问题的组合。我们须要遍历全部的k值i≤k≤j?1即考查所用的划分点。

2.递归求解方案

令m[i,j],i≤j标示矩阵链?Ai,Ai+1,Ai+2...Aj?的最优括号化方案所需乘法次数的最小值。

当i=j时。m[i,j]=0,仅仅有一个矩阵不涉及乘法运算

当i<j时。假设在矩阵链?Ai,Ai+1,Ai+2...Aj?切割点位置为Ak和Ak+1之间,如上分析,m[i,j]为m[i,k]与m[k+1,j]的代价和,还要加上两者最后相乘涉及的运算次数。假如Ai的大小为pi?1×pi,则子矩阵链m[i,k]乘积后的矩阵大小为pi?1×pk, m[k+1,j]乘积后的大小为pk×pj,所以最后一次乘积做的乘法运算次数为pi?1pkpj。

即:

m[i,j]=0,(i=j)

m[i,j]=min{m[i,k]+m[k+1,j]+pi?1pkpj},i<j,i≤k≤j?1

3.计算最优代价

递归算法会多次遇到同一个子问题。与钢铁切割非常相似,每一次高层的运算,都会调用底层结果。越是底层,被调用的次数越多。所以能够採用自底向上的方法,先对底层逐个求解,当上层须要调用底层时,底层已经被求解完成。

用m[i][j]二维矩阵保存相应链?Ai,Ai+1,Ai+2...Aj?长度为j-i+1的最优计算代价q。

用s[i][j]二维矩阵保存相应链?Ai,Ai+1,Ai+2...Aj?长度为j-i+1的最优划分位置k。

void Matrix_Chain_Order(int p[],int n)
{
   int i,j,L,k,q;
   for (i=1;i<=n;i++)      //先对单个矩阵的链,求解,即全部m[i][i] =0;
   {
     m[i][i]=0;
   }
   for(L=2;L<=n;L++)     //从两个矩阵链的长度開始,逐次添加矩阵链的长度
       for(i=1;i<=n-L+1;i++)  //在给定p[]中的矩阵链中,对全部种长度为L的情况计算
       {
           j = i+L-1;
           m[i][j] = -1;
           for(k=i;k<=j-1;k++)   //遍历全部可能的划分点k。计算出最优的划分方案
           {
             q = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];//计算划分的代价
             if ( q < m[i][j] || m[i][j] == -1)
             {
                m[i][j] = q;     //最优的代价q保存在m[i][j]中
                s[i][j] = k;     //最优的划分位置k保存在s[i][j]中
             }
           }
       }

}

构造最优解

矩阵链?Ai,Ai+1,Ai+2...Aj?。因为二维矩阵s[i][j]记录了相应划分位置k,指出了应该在Ak和Ak+1之间。相同在矩阵链\left[中最优划分位置一定保存在数组s[i][s[i,j]]内,矩阵;链?Ak+1,Ak+2...Aj?的最优划分位置一定保存在s[s[i][j]+1]][j]数组内。能够不断递归出最优解。

例程

/************************************************************************
CSDN 勿在浮沙筑高台
http://blog.csdn.net/luoshixian099
算法导论--动态规划(矩阵链乘法)
2015年6月3日
************************************************************************/
#include <STDIO.H>
#include <STDLIB.H>
int m[7][7]={0};
int s[7][7]={0};
void Print_Optimal_Parens(int s[][7],int i,int j)  //构造最优解
{
   if ( i ==j)
   {
       printf("A%d",i);
   }
   else
   {
       printf("(");
       Print_Optimal_Parens(s,i,s[i][j]);
       Print_Optimal_Parens(s,s[i][j]+1,j);
       printf(")");
   }
}
void Matrix_Chain_Order(int p[],int n)
{
   int i,j,L,k,q;
   for (i=1;i<=n;i++)      //先对单个矩阵的链,求解,即全部m[i][i] =0;
   {
     m[i][i]=0;
   }
   for(L=2;L<=n;L++)     //从两个矩阵链開始,逐次添加矩阵链的长度
       for(i=1;i<=n-L+1;i++)  //在给定p[]中的矩阵链中,对全部种长度为L的情况计算
       {
           j = i+L-1;
           m[i][j] = -1;
           for(k=i;k<=j-1;k++)   //遍历全部可能的划分点k。计算出最优的划分方案,
           {
             q = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
             if ( q < m[i][j] || m[i][j] == -1)
             {
                m[i][j] = q;     //最优的代价q保存在m[i][j]中
                s[i][j] = k;     //最优的划分位置k保存在s[i][j]中
             }
           }
       }

}
void main()
{
    int p[]={30,35,15,5,10,20,25};    //矩阵的输入
    int length = sizeof(p)/sizeof(p[0])-1;   //矩阵长度
    int i,j;
    Matrix_Chain_Order(p,length);

    for(i =1;i<=6;i++)
    {
        for (j=1;j<=6;j++)
        {
            printf("%8d",m[i][j]);
        }
        printf("\n");
    }

    Print_Optimal_Parens(s,1,6);
    printf("\n");
}

时间: 2024-10-15 14:37:53

算法导论--动态规划(矩阵链乘法)的相关文章

动态规划-矩阵链乘法

问题描述: 给定由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

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

什么是矩阵链乘法(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?)):  我们要做的就

《算法导论》读书笔记之动态规划—矩阵链乘法

前言:今天接着学习动态规划算法,学习如何用动态规划来分析解决矩阵链乘问题.首先回顾一下矩阵乘法运算法,并给出C++语言实现过程.然后采用动态规划算法分析矩阵链乘问题并给出C语言实现过程. 1.矩阵乘法 从定义可以看出:只有当矩阵A的列数与矩阵B的行数相等时A×B才有意义.一个m×r的矩阵A左乘一个r×n的矩阵B,会得到一个m×n的矩阵C.在计算机中,一个矩阵说穿了就是一个二维数组.一个m行r列的矩阵可以乘以一个r行n列的矩阵,得到的结果是一个m行n列的矩阵,其中的第i行第j列位置上的数等于前一个

第十五章 动态规划——矩阵链乘法

前言:今天接着学习动态规划算法,学习如何用动态规划来分析解决矩阵链乘问题.首先回顾一下矩阵乘法运算法,并给出C++语言实现过程.然后采用动态规划算法分析矩阵链乘问题并给出C语言实现过程. 1.矩阵乘法 从定义可以看出:只有当矩阵A的列数与矩阵B的行数相等时A×B才有意义.一个m×r的矩阵A左乘一个r×n的矩阵B,会得到一个m×n的矩阵C.在计算机中,一个矩阵说穿了就是一个二维数组.一个m行r列的矩阵可以乘以一个r行n列的矩阵,得到的结果是一个m行n列的矩阵,其中的第i行第j列位置上的数等于前一个

动态规划—矩阵链乘法

矩阵链乘问题描述 给定n个矩阵构成的一个链<A1,A2,A3,.......An>,其中i=1,2,...n,矩阵A的维数为pi-1pi,对乘积 A1A2...An 以一种最小化标量乘法次数的方式进行加全部括号. 注意:在矩阵链乘问题中,实际上并没有把矩阵相乘,目的是确定一个具有最小代价的矩阵相乘顺序.找出这样一个结合顺序使得相乘的代价最低. 动态规划分析过程 1)最优加全部括号的结构 动态规划第一步是寻找一个最优的子结构.假设现在要计算AiAi+1....Aj的值,计算Ai...j过程当中肯

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

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

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

算法导论 之 动态规划 - 矩阵链相乘

1 引言 在大学期间,我们学过高等数学中的线性规划,其中有关于矩阵相乘的章节:只有当矩阵A的列数与矩阵B的行数相等时,A×B才有意义.一个m×n的矩阵A(m,n)左乘一个n×p的矩阵B(n,p),会得到一个m×p的矩阵C(m,p).矩阵乘法满足结合律,但不满足交换律. 假设现要计算A×B×C×D的值,因矩阵乘法满足结合律,不满足交换律,即:A.B.C.D相邻成员的相乘顺序不会影响到最终的计算结果,比如: A×(B×(C×D)).A×((B×C)×D).(A×B)×(C×D).A×(B×C)×D.

算法导论------------------动态规划之矩阵链问题

[问题描述] 给定有n个连乘矩阵的维数,要求计算其采用最优计算次序时所用的乘法次数,即所要求计算的乘法次数最少.例如,给定三个连乘矩阵{A1,A2,A3}的维数分别是10*100,100*5和5*50,采用(A1A2)A3,乘法次数为10*100*5+10*5*50=7500次,而采用A1(A2A3),乘法次数为100*5*50+10*100*50=75000次乘法,显然,最好的次序是(A1A2)A3,乘法次数为7500次. 分析: 矩阵链乘法问题描述: 给定由n个矩阵构成的序列[A1,A2,.