首页 > 代码库 > 动态规划—矩阵链乘法

动态规划—矩阵链乘法

矩阵链乘问题描述

给定n个矩阵构成的一个链<A1,A2,A3,.......An>,其中i=1,2,...n,矩阵A的维数为pi-1pi,对乘积 A1A2...A以一种最小化标量乘法次数的方式进行加全部括号。

注意:在矩阵链乘问题中,实际上并没有把矩阵相乘,目的是确定一个具有最小代价的矩阵相乘顺序。找出这样一个结合顺序使得相乘的代价最低。

动态规划分析过程

1)最优加全部括号的结构

  动态规划第一步是寻找一个最优的子结构。假设现在要计算AiAi+1....Aj的值,计算Ai...j过程当中肯定会存在某个k值(i<=k<j)将Ai...j分成两部分,使得Ai...j的计算量最小。分成两个子问题Ai...k和Ak+1...j,需要继续递归寻找这两个子问题的最优解。

  有分析可以到最优子结构为:假设AiAi+1....Aj的一个最优加全括号把乘积在Ak和Ak+1之间分开,则Ai..k和Ak+1..j也都是最优加全括号的。

2)一个递归解

  设m[i,j]为计算机矩阵Ai...j所需的标量乘法运算次数的最小值,对此计算A1..n的最小代价就是m[1,n]。现在需要来递归定义m[i,j],分两种情况进行讨论如下:

当i==j时:m[i,j] = 0,(此时只包含一个矩阵)

当i<j 时:从步骤1中需要寻找一个k(i≤k<j)值,使得m[i,j] =min{m[i,k]+m[k+1,j]+pi-1pkpj} (i≤k<j)。

3)计算最优代价

  虽然给出了递归解的过程,但是在实现的时候不采用递归实现,而是借助辅助空间,使用自底向上的表格进行实现。设矩阵Ai的维数为pi-1pi,i=1,2.....n。输入序列为:p=<p0,p1,...pn>,length[p] = n+1。使用m[n][n]保存m[i,j]的代价,s[n][n]保存计算m[i,j]时取得最优代价处k的值,最后可以用s中的记录构造一个最优解。书中给出了计算过程的伪代码,摘录如下:

MAXTRIX_CHAIN_ORDER(p)
 2   n = length[p]-1;
 3   for i=1 to n
 4       do m[i][i] = 0;
 5   for t = 2 to n  //t is the chain length
 6        do for i=1 to n-t+1
 7                      j=i+t-1;
 8                      m[i][j] = MAXLIMIT;
 9                      for k=i to j-1
10                             q = m[i][k] + m[k+1][i] + qi-1qkqj;
11                             if q < m[i][j]
12                                then m[i][j] = q;
13                                     s[i][j] = k;
14   return m and s;

 

MATRIX_CHAIN_ORDER具有循环嵌套,深度为3层,运行时间为O(n3)。如果采用递归进行实现,则需要指数级时间Ω(2n),因为中间有些重复计算。

4)构造一个最优解

第三步中已经计算出来最小代价,并保存了相关的记录信息。因此只需对s表格进行递归调用展开既可以得到一个最优解。书中给出了伪代码,摘录如下:

 

PRINT_OPTIMAL_PARENS(s,i,j)
   if i== j 
      then print "Ai"
   else
      print "(";
      PRINT_OPTIMAL_PARENS(s,i,s[i][j]);
      PRINT_OPTIMAL_PARENS(s,s[i][j]+1,j);
      print")";

 

5)编程实现

写完传

 

动态规划—矩阵链乘法