zoukankan      html  css  js  c++  java
  • 动态规划之矩阵连乘

    给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2 ,…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

    例如:

      A1={30x35} ; A2={35x15} ;A3={15x5} ;A4={5x10} ;A5={10x20} ;A6={20x25} ;

    结果为:((A1(A2A3))((A4A5)A6))  最小的乘次为15125。

    原问题为n个矩阵连乘,将原问题分解为子问题,即当n等于1,2,3.....时。

    n==1时,单一矩阵,不需要计算。最小乘次为0

    n==2时,根据n==1时的结果,遍历计算出每相邻两个矩阵的最小乘次

    n==3时,根据n==1和n==2时的结果,此时已经求出每相邻1个、2个矩阵的最小乘次,遍历计算出该相邻三个矩阵的最小乘次

    依次类推……

    n==n时,根据n==1、2、……n-1时的结果,此时已经求出每相邻1个、2个、3个……n-1个矩阵的最小乘次,由此求出n==n时的最小乘次

    每当n增加1时,就利用已求出的子结构来求解此时的最优值。

    数学描述如下:

    设矩阵Ai的维数为P× Pi+1

    A[i:j]为矩阵AiAi+1....Aj的连乘积,即从Ai到Aj的连乘积,其中,0 <= i <= j <= n-1

    设m[i][j]为计算A[i:j]的最小乘次,所以原问题的最优值为m[0][n-1]

    当 i==j 时,单一矩阵,无需计算。m[i][i]=0,i=0,1,....n-1

    当 i < j 时,利用最优子结构,计算m[i][j]。即寻找断开位置k(i <= k < j),使得m[i][k]+m[k+1][j]+Pi*Pk+1*Pj+1最小。

    该算法的python实现:

     1 # coding=gbk
     2 # 矩阵连乘问题
     3 __author__ = 'ice'
     4 
     5 
     6 # row_num 每个矩阵的行数
     7 class Matrix:
     8     def __init__(self, row_num=0, col_num=0, matrix=None):
     9         if matrix != None:
    10             self.row_num = len(matrix)
    11             self.col_num = len(matrix[0])
    12         else:
    13             self.row_num = row_num
    14             self.col_num = col_num
    15         self.matrix = matrix
    16 
    17 
    18 def matrix_chain(matrixs):
    19     matrix_num = len(matrixs)
    20     count = [[0 for j in range(matrix_num)] for i in range(matrix_num)]
    21     flag = [[0 for j in range(matrix_num)] for i in range(matrix_num)]
    22     for interval in range(1, matrix_num + 1):
    23         for i in range(matrix_num - interval):
    24             j = i + interval
    25             count[i][j] = count[i][i] + count[i + 1][j] + matrixs[i].row_num * matrixs[i + 1].row_num * matrixs[j].col_num
    26             flag[i][j] = i
    27             for k in range(i + 1, j):
    28                 temp = count[i][k] + count[k + 1][j] + matrixs[i].row_num * matrixs[k + 1].row_num * matrixs[j].col_num
    29                 if temp < count[i][j]:
    30                     count[i][j] = temp
    31                     flag[i][j] = k
    32     traceback(0, matrix_num - 1, flag)
    33     return count[0][matrix_num - 1]
    34 
    35 
    36 def traceback(i, j, flag):
    37     if i == j:
    38         return
    39     if j - i > 1:
    40         print(str(i + 1) + '~' + str(j + 1), end=': ')
    41         print(str(i + 1) + ":" + str(flag[i][j] + 1), end=',')
    42         print(str(flag[i][j] + 2) + ":" + str(j + 1))
    43     traceback(i, flag[i][j], flag)
    44     traceback(flag[i][j] + 1, j, flag)
    45 
    46 
    47 matrixs = [Matrix(30, 35), Matrix(35, 15), Matrix(15, 5), Matrix(5, 10), Matrix(10, 20), Matrix(20, 25)]
    48 result = matrix_chain(matrixs)
    49 print(result)
    50 
    51 # 1~6: 1:3,4:6
    52 # 1~3: 1:1,2:3
    53 # 4~6: 4:5,6:6
    54 # 15125
  • 相关阅读:
    刚体
    Unity3D游戏开发之数据持久化PlayerPrefs的使用
    用AudioSource.PlayClipAtPoint播放音效
    按非降序建立n个元素的线性表
    Unity中的Transform.SetParent()API
    带头结点的两个链表La,Lb,将两个链表合并到La中,并且不破坏Lb的结构
    不带头结点的两个链表合并为一个链表
    二叉树的相关操作(c语言)
    关于ajax请求数据,并将数据赋值给全局变量的一些解决方法
    SummerVocation_Leaning--java动态绑定(多态)
  • 原文地址:https://www.cnblogs.com/z941030/p/4922118.html
Copyright © 2011-2022 走看看