动态规划算法---矩阵连乘(C语言)

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

一 分析最优解的性质与结构
最优解也就是计算A[1:n]的最优次序,可以假设这个最优解在第k处断开,1<=k<j,则A[1:j]是最优的,那么A[1,k]和A[k+1:j]也是相应矩阵连乘的最优解。
关键在于矩阵乘积计算次序问题的最优解包含着其子问题的最优解,这种性质是最优子结构性质。
二 建立递归关系
![在这里
其中m[i][j]表示最少数乘次数,也就是构建最优解的代价。
其中pi-1pkpj表示前两部分相乘的代价。(Ai的维数可以表示为pi-1*pi).
三 计算最优值并解决子问题重叠问题
子问题重叠:
根据以上递归中,可以知道有些子问题例如m[1,2]被不同的子问题包含,可能被计算多次。
解决办法:
根据递归形式以自底向上的方式进行计算,在计算过程中保存已解决的子问题答案,从而避免重复计算。
具体:
数组m[n][n]存取最优值,数组s[n][n]表示分割位置,按照递增的方式逐步填写子问题的解,也就是先计算长度为2的所有矩阵链的解,然后计算长度3的矩阵链,直到长度n。
m[i][i]=0(矩阵链长为1)
m[i][i+1] (链长为2)

所以当计算m[i][j]时只用到了m[i][k]和m[k+1][j]。

四 构造最优解
从s[1][n]中可知,最优加括号方式应为(A[1:s[1][n])(A[s[1][n]+1:n)。
A[i:s[1][n])的最优加括号方式为A[1:s[1][s[1][n]]])(A[s[1][s[1][n]]]+1:s[1][n]])…
最终可以构造原问题的最优解。

#include <stdio.h>
#include <stdlib.h>
void MatrixChain(int p[6],int n,int m[][7],int s[][7])
{
int r=0,i=0,j=0,k=0,t=0;
for(i=1;i<=n;i++)
    m[i][i]==0;
for(r=2;r<=n;r++)
for(i=1;i<=n-r+1;i++)//n-r+1表示保证有r个矩阵相乘
{
    j=i+r-1;//当r=3时 有三个矩阵 但j=i+2,所以需要-1
    m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];//默认在初始下标之后断开,得到初始值
    s[i][j]=i;
    for(k=i+1;k<j;k++)
    {
        t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
        if(t<m[i][j]){
            m[i][j]=t;
            s[i][j]=k;
        }

    }
}
}
void TrackBack(int i,int j, int s[][7])
{
    if(i==j) return;
    TrackBack(i,s[i][j],s);//递归第一次断开之前
    TrackBack(s[i][j]+1,j,s);
    printf("A%d",i);
    printf(" and A%d",j);
    printf("\n");

}
int main()
{
   int n=6;
   int p[]={30,35,15,5,10,20,25};
   int s[7][7]={0};
   int m[7][7]={0};
   MatrixChain(p,n,m,s);
   TrackBack(1,n,s);
}

结果
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值