动态规划之矩阵链乘法

矩阵链相乘

矩阵链乘法
求解矩阵链相乘问题时动态规划算法的另一个例子。给定一个n个矩阵的序列(矩阵链)<A1,A2,...,An>,我们希望计算它们的乘积 A1A2...An

?两个矩阵A和B只有相容(compatible),即A的列数等于B的行数时,才能相乘。如果A是p×q的矩阵,B是q×r的矩阵,那么乘积C是p×r的矩阵。计算C所需要时间由第8行的标量乘法的次数决定的,即pqr。
? ?以矩阵链<A1,A2,A3>为例,来说明不同的加括号方式会导致不同的计算代价。假设三个矩阵的规模分别为10×100、100×5和5×50。
? ?如果按照((A1A2)A3)的顺序计算,为计算A1A2(规模10×5),需要做10×100×5=5000次标量乘法,再与A3相乘又需要做10×5×50=2500次标量乘法,共需7500次标量乘法。
? ?如果按照(A1(A2A3))的顺序计算,为计算A2A3(规模100×50),需100×5×50=25000次标量乘法,再与A1相乘又需10×100×50=50000次标量乘法,共需75000次标量乘法。因此第一种顺序计算要比第二种顺序计算快10倍。

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

递推关系式

https://blog.csdn.net/Neo_kh/article/details/81282025
①如果i=j,m[i,j]=0

②如果i<j,m[i,j]=min{m[i,k]+m[k+1,j]+p(i-1)p(k)p(j)}  i<=k<j
#include <bits/stdc++.h>
#define max_size 400
#define INF 100000000
long long s[max_size][max_size];//保存构造最优解信息
long long p[max_size];//矩阵规模的记录
long long m[max_size][max_size];//记录最优值

void  matrix_chain_order(int n)
{
    for(int i=1;i<=n;i++)
    {
        m[i][i]=0;//初始化最优值(起始于1,结束于n)
    }
    for(int l=2;l<=n;l++)//l表示矩阵链的长度
    {//计算每一条对角线的最优值
        for(int i=1;i<=n-l+1;i++)
        {
            int j=i+l-1;
            m[i][j]=INF;
            s[i][j]=0;
            for(int k=j-1;k>=i;k--)//解决方案优先选取先左边的矩阵
            {//②如果i<j,m[i,j]=min{m[i,k]+m[k+1,j]+p(i-1)p(k)p(j)}  i<=k<j
                int 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;
                }
            }
        }
    }
}

void print_optimal_parents(int i,int j)//打印最优解的结果
{
    if(i==j)
        printf("A%d",i);
    else
    {   //中序二叉树?
            printf("(");
            print_optimal_parents(i,s[i][j]);
            print_optimal_parents(s[i][j]+1,j);
            printf(")");
    }
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(p,0,sizeof(p));
        for(int i=0;i<=n;i++)
        {
            scanf("%lld",&p[i]);
        }
        matrix_chain_order(n);
        print_optimal_parents(1,n);
        printf("\n");
    }
}

小结:
动态规划算法设计要素
1.多阶段决策过程,每步处理一个子问题,界定子问题的边界
2.列出优化函数的递推方程及初值
3.问题要满足优化原则或最优子结构性质,即:一个最优决策序列的任何子序列本身一定是相对于子序列的
初始和结束状态的最优决策序列
拓展: 递归实现

#include<string>
#include<cstring>
#include<iostream>
using namespace std;

int n;
int p[100];
int m[100][100];
int s[100][100];
int dp(int i,int j){
    if(i==j)               /*如果只有一个矩阵就直接返回*/
        return m[i][j];
    m[i][j]=999999999;     /*将m[i][j]设为无穷大*/
    s[i][j]=i;
    for(int k=i;k<j;k++){  /*将i到j个矩阵分为i到k和k+1到j个矩阵*/
        int q=dp(i,k)+dp(k+1,j)+p[i-1]*p[k]*p[j];
        if(q<m[i][j]){      /*如果有更小的方案更新*/
            m[i][j]=q;
            s[i][j]=k;
        }
    }
    return m[i][j];
}
int main(){
    while(cin>>n){
        for(int i=0;i<=n;i++){  /*输入矩阵链*/
            cin>>p[i];
        }
        memset(m,0,sizeof(m));    /*初始化*/
        dp(1,n);                    /*查找目标1到n个矩阵链乘*/
        cout<<m[1][n]<<" "<<s[1][n]<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/jason1999/p/11365930.html

时间: 2024-10-10 03:45:12

动态规划之矩阵链乘法的相关文章

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

矩阵链乘法问题 给定一个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

[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

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

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

动态规划-矩阵链乘法

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

矩阵链乘法(动态规划)

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

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

前言:今天接着学习动态规划算法,学习如何用动态规划来分析解决矩阵链乘问题.首先回顾一下矩阵乘法运算法,并给出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列位置上的数等于前一个

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

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

算法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