zoukankan      html  css  js  c++  java
  • DP之矩阵连乘问题

    最优二叉查找树的一道思考习题

    同最优二叉查找树一样,矩阵连乘问题也是一个卡特兰数问题(其动态规划的构造过程都很像)


    分析解答:
    a,铺垫的数学知识首先要搞清楚矩阵相乘是怎么乘的:

    1)对于连续的n个矩阵相乘 A1 * A2 *A3.........An,其乘法顺序可以是任意的,可以在上面加括号,改变做乘法的顺序,例如 A*B*C三个矩阵相乘可以A*(B*C)

    也可以直接按从左到右的顺序。连续的两个矩阵的位数必须满足m*p,p*n才能相乘,且相乘后的结果是个m*n的矩阵。(线性代数的知识)

    2)对于2个m*p,p*n的矩阵相乘,共做乘法次数为 m*n*p 次。这是预备知识,知道矩阵连续的乘法的运算次数跟运算顺序有关后,就很容易举出例子了,略。
    b,卡特兰数个,证明很麻烦,有时间看了组合数学再来看
    c,重点是要解决这个问题。


    设M[i , j]表示从第 i 个矩阵到第 j 个矩阵连乘的最少乘法次数,(i 从 0 编号),我们最终的目标是求 M[0 , n-1]。

    Ai *.......Ak * Ak+1.....Aj

    假设要得到这个式子的值(即从矩阵 i 连乘到矩阵 j),所作的最后一个矩阵乘法是在矩阵 k 后(注意准确的描述位置)断开的(即左右都已乘运算好),那么容易得到

    其递推式:

    M[i , j]  =  min{ M[i , k] + M[k+1 , j]  + p[i - 1] * p[ k ] * p[ j ] }         i   <=   k   <=   j-1

    其中 di 是矩阵 Ai 的第一维,dk+1是断开处矩阵 Ak 的第二维(即Ak+1的第一维,是一样的),dj+1是最后一个矩阵 Aj 的第二维。

    得到这个式子也是一个逆向思维的过程。


    可以用矩阵连乘的动态规划构造过程与最优二叉查找树比较下,发现其构造非常相似(在前面一篇dp之什么叫做professional中提到过,不再详述)

    实现:

    初始条件:M[i , i] = 0

    填表顺序:鉴于其递推式与最优二叉查找树相似,填表顺序也是按对角线的,自己画画就知道了。

    代码也跟最优二叉查找树的控制逻辑相似:

     

    package Section8;


    /*第八章 动态规划   课后习题:矩阵连乘*/

    public class MatEven {

        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int[] Dim = {30,35,35,15,15,5,5,10,10,20,20,25};
            int result = MatEven(Dim);

            System.out.println(" 动态规划求的的最优策略相乘顺序导致的最少乘法数为:" + result);
        }
       
        public static int MatEven(int[] Dim){
            //接受n个矩阵的维度数组Dim大小为2n
            int n = Dim.length / 2;        //有n个矩阵,编号0...n-1,编号为k的矩阵的维数是Dim[2k] * Dim[2k+1]
           
            int[][] Result = new int[n][n];        //最小代价矩阵
           
            //初始化
            for(int i = 0;i < n;i++)
                Result[i][i] = 0;
           
            //沿对角线填矩阵
            for(int d = 1;d <= n-1;d++)      //共n-1条对角线需要填
            {
                for(int i = 0;i <= n-d-1;i++)    //第d条对角线的第一个点横坐标为d
                {
                    //int j = i - d;
                    int j = i + d;        //在第d条对角线上的点,横纵坐标的关系是j = i + d
                   
                    //这样就确定了一个位置(i,j)的坐标,然后来填(i,j)
                    int Min = 1000000000;
                    for(int k = i;k <= j-1;k++)        //从第k个矩阵后面断开
                    {
                        //动态规划状态转移方程
                        int temp = Result[i][k] + Result[k+1][j] + (Dim[2*i] * Dim[2*k + 1] * Dim[2*j+1]);
                        if( temp < Min)
                            Min = temp;
                    }
                   
                    Result[i][j] = Min;
                }
               
            }
           
            return Result[0][n-1];
        }
    }

     



    上面用一个数组接受一个连乘的矩阵的维数,

    例如连乘的矩阵维数是:30*35  35*15  15*5  5*10  10*20  20*25

    用动态规划求解得到的最佳乘法次数是:


    动态规划求的的最优策略相乘顺序导致的最少乘法数为:15125

    直接返回矩阵的话就可以得到整个M[i , j]的值

    如果按照从左到右的顺序做乘法,是远远不止这个次数的。


    -------------------------------------------------------------------------

    当然,再做一些处理,就还可以得到具体的次序,类似于最优二叉查找树,就是要记录动态规划产生的过程,略

    ----------------------------------------------------------------------------------------------


    总结:


    矩阵连乘问题是个卡特兰数问题

    其动态规划的构造过程非常类似于最优二叉查找树

    矩阵连乘的最有子结构是什么?

  • 相关阅读:
    PAT (Advanced Level) 1060. Are They Equal (25)
    PAT (Advanced Level) 1059. Prime Factors (25)
    PAT (Advanced Level) 1058. A+B in Hogwarts (20)
    PAT (Advanced Level) 1057. Stack (30)
    PAT (Advanced Level) 1056. Mice and Rice (25)
    PAT (Advanced Level) 1055. The World's Richest (25)
    PAT (Advanced Level) 1054. The Dominant Color (20)
    PAT (Advanced Level) 1053. Path of Equal Weight (30)
    PAT (Advanced Level) 1052. Linked List Sorting (25)
    PAT (Advanced Level) 1051. Pop Sequence (25)
  • 原文地址:https://www.cnblogs.com/yaowen/p/4466268.html
Copyright © 2011-2022 走看看