dp经典问题之矩阵连乘问题

dp经典问题之矩阵连乘问题

  • 问题描述

  • 思路分析

    1. 这个问题很明显可以用递归的思路的思考,先把连乘的矩阵分成两部分,分别递归地算出左边部分连乘需要的乘法次数和右边部分连乘需要乘法次数,最后计算两部分连乘的结果相乘的需要的乘法次数,求和得出需要的乘法总数。
    2. A1* A2*A3可以分成A1*A2 和A3两部分,树结构如下。当然也可以分成A1和A2*A3两部分,所以划分的时候需要确定从哪个地方划分,最后取乘法次数最小的那个划分。

因此可以写出递归方程


// Am*Am+1*Am+2……An 需要的最小乘法次数为f(m,n)
// 假设Am 中m表示矩阵的行为m,列为m+1
if(m==n){
   f(m,n) = 0
}

if(m > n){
   f(m,n) = f(m,k) + f(k+1, n) + m * (k+1) * (n + 1); //m * (k+1) * (n + 1) 为两部分相乘需要的乘法次数 Am……Ak 得到m行,k+1列。Ak+1……An得到k+1行,n+1列。所以需要m*(k+1)*(n+1)次乘法 
}
  • 继续思考, 这样的话,我直接利用递归就把这道题解决了, 还用dp?贴一下时间复杂度,好难推导啊!

  • 仔细思考不难发现,计算的时候很容易出现重复计算,A1*A2*A3*A4*A5 分成A1*A2*A3和A4*A5, 又可以分成A1*A2和A3*A4*A5, A1*A2明显存在重复利用。

  • 利用dp解决重复计算问题

    **我的思路是在自顶向下的时候利用一个全局的hashmap保存计算结果, 遇到重复的就从hashmap里面拿 **

    但是dp都是自低向上的,消除递归

  • 算法思路

    //1. 声明二维矩阵dp[n][n],dp[i][j]表示Ai……Aj需要的乘法次数
    //2. 声明矩阵s[n][n],s[i][j]用来表示Ai……Aj中的最优划分
    //3. 接下来初始化矩阵dp
    // 3.1 连乘的矩阵个数为1,即dp[i][j]中,i==j,令dp[i][j]==0
    // 3.2 连乘矩阵个数为2,计算dp[i][i+1],例如dp[1][2],dp[2][3]
    // 4. 连乘矩阵个数大于3,利用状态转移方程计算dp[i][j] = dp[i][k] + dp[k+1][j] + i *(k+1) * (j+1),填写相应的s矩阵
    // 5.利用s计算最佳计算顺序
    
    
posted @ 2020-10-12 23:27  FizzPu  阅读(206)  评论(0编辑  收藏  举报