动态规划——矩阵链乘法

矩阵链乘法
问题描述:给定n个矩阵构成的一个链<A[1], A[2], ... , A[n]>,其中i = 1, 2, ... , n,矩阵A[i]的维数为p[i-1]*p[i],对乘积A[1]A[2]...A[n]以一种最小化标量乘法次数的方式进行加全部括号。
步骤1:最优加全部括号的结构
用记号A[i..j]表示乘积A[i]A[i+1]...A[j]求值的结果,其中i <= j。假设A[i]A[i+1]...A[j]的一个最优加全部括号把乘积在A[k]和A[k+1]之间分开,则对A[i]A[i+1]...A[j]最优加全部括号的“前缀”子链A[i]A[i+1]...A[k]的加全部括号必须是A[i]A[i+1]...A[k]的一个最优加全部括号。
步骤2:一个递归解
设m[i][j]为计算矩阵A[i..j]所需的标量乘法运算次数的最小值;对整个问题,计算A[1..n]的最小代价就是m[1][n]。
假设最优加全部括号将乘积A[i]A[i+1]...A[j]从A[k]和A[k+1]之间分开,i <= k < j。则:
m[i][j] = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]
关于对乘积A[i]A[i+1]...A[j]加全部括号的最小代价的递归定义为:
m[i][j] = 0 if i == j
m[i][j] = min(i<=k<j){m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]} if i < j
步骤3:计算最优代价
用迭代自底向上的表格法来计算最优代价。
步骤4:构造一个最优解
利用保存在表格s[n][n]内的、经过计算的信息来构造一个最优解。按最优方式计算A[1..n]时,最终矩阵相乘次序是A[1..s[1][n]]A[a[1][n]+1..n]。之前的乘法可以递归地进行。 

MatrixChainMain.c

#include  < stdio.h >
#include 
< limits.h >
#define  LENGTH    6

/*
 *p[i]:矩阵Ai的列数或Ai-1的行数
 *m[i][j]:纪录Ai - Aj的矩阵连乘的最小代价
 *s[i][j]:纪录Ai - Aj之间得到最小连乘代价时的分割点
 
*/

void  MatrixChainOrder( int  p[],  int  m[][LENGTH],  int  s[][LENGTH])
{
    
int i, j, k, len, q;

    
for(i=0; i<LENGTH; i++)
        m[i][i] 
= 0;
    
for(len=2; len<=LENGTH; len++)    //len为矩阵链的长度
    {
        
for(i=0; i<(LENGTH-len+1); i++)
        
{
            j 
= i + len - 1;
            m[i][j] 
= INT_MAX;
            
//计算Ai - Aj最优代价
            for(k=i; k<j; k++)
            
{
                q 
= m[i][k] + m[k+1][j] +p[i]*p[k+1]*p[j+1];
                
if(q < m[i][j])
                
{
                    m[i][j] 
= q;
                    s[i][j] 
= k;
                }

            }

        }

    }

}


void  PrintOptimalParens( int  s[][LENGTH],  int  i,  int  j)
{
    
if(i == j)
        printf(
"A%d", i);
    
else
    
{
        printf(
"(");
        PrintOptimalParens(s, i, s[i][j]);
        PrintOptimalParens(s, s[i][j]
+1, j);
        printf(
")");
    }

}


int  main( int  argc,  char   ** argv)
{
    
int p[LENGTH+1= {3035155102025};
    
int m[LENGTH][LENGTH];
    
int s[LENGTH][LENGTH];

    MatrixChainOrder(p, m, s);
    PrintOptimalParens(s, 
0, LENGTH-1);
    printf(
" ");

    
return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值