zoukankan      html  css  js  c++  java
  • 动态规划 矩阵链乘法

    矩阵链乘法

    n个矩阵相乘,A1A2...An,试着找到一种相乘顺序,使得整个相乘的过程中所做的标量乘法次数最少,即相乘的代价最小。

    问题分析:

      记矩阵Ai的行列分别为Pi-1和Pi,那么A1*A2所做的乘法的次数为P0*P1*P2

    A1A2...An的最小相乘代价为f(1,n),Ai...Aj的最小相乘代价为f(i,j)

    则 f(1,n) = min{f(1,k)+f(k+1,n)+P0*Pk*Pn} k=1...n-1

    f(i,i)=0  f(i,i+1)=Pi-1*Pi*Pi+1

    So 可以由此产生递归式

     1 Recursive_Matrix_Multiply(p, i, j)
    2 {
    3 if(i==j)
    4 return 0;
    5 f[i][j] = max_int;
    6 for(k=i;k<j;k++)
    7 {
    8 q=Recursive_Matrix_Multiply(p,i,k)+Recursive_Matrix_Multiply(p,k+1,j)+p[i-1]*p[k]*p[j];
    9 if(q<f[i][j])
    10 {
    11 f[i][j]=q;
    12 s[i][j]=k;
    13 }
    14 }
    15 return f[i][j];
    16 }

    其中s[i][j]记录的是Ai...Aj相乘的最小代价的分割点,即先计算Ai...Ak,再计算Ak+1...Aj,然后再将结果相乘,Ai...Aj的相乘代价最小

    递归的解法看起来思路清晰,但时间复杂度太高

    若记n个矩阵的时间复杂度为T(n),则T(n)=∑k=1..n-1{T(k) + T(n-k) + c}, 可以推断T(n)>=2n

    分析递归的过程可以发现,有很多子问题被重复计算过了,比如计算A1...A3的过程中需要A2A3,在A1...Aj,j>3的过程中,也都需要A2A3,如果我们能够自底向上开始计算Ai..Aj,并把结果记录下来,后面用到的时候直接查询就可获得,就可以降低时间复杂度了

    于是,有了以下自底向上的解法

     1 Matrix_Chain_Order(p, 1, n)
    2 {
    3 for(t=1;t<n+1;i++)
    4 f[t][t]=0;
    5 for(m=2;m<n;m++)
    6 {
    7 for(i=1;i<=n-m+1;i++)
    8 {
    9 j=i+m-1;
    10 f[i][j]=max_int;
    11 for(k=i;k<j;k++)
    12 {
    13 q = f[i][k]+f[k+1][j]+p[i-1]*p[k]*p[j];
    14 if(q<f[i][j])
    15 {
    16 f[i][j]=q;
    17 s[i][j]=k;
    18 }
    19 }
    20 }
    21 }
    22 return f and s;
    23 }

    三层循环,每一层中的循环变量值至多为n-1,故时间复杂度为O(n3),时间复杂度有指数级 降低到了多项式时间,而付出的代价是增加了O(n2)的辅助空间

    动态规划的思想就是以空间为代价,降低算法的时间复杂度


  • 相关阅读:
    iframe的边框如何去掉
    vue-computed计算属性用法
    Vue-input框checkbox强制刷新
    TED 积极心理学感悟(二)
    路由器使用子网掩码进行分组转发的过程
    DHCP 服务器和 DHCP 客户端的交互过程
    IPv4 协议中的 NAT 协议和 CIDR 协议
    IPv6 是解决 IPv4 地址耗尽问题的根本途径
    TED 积极心理学感悟
    初级错误之 for 中的局部变量
  • 原文地址:https://www.cnblogs.com/un4sure/p/2400867.html
Copyright © 2011-2022 走看看