动态规划之矩阵连乘

假设矩阵A1:m*n , A2:n*p ,则A1*A1:m*p ,其中它们相乘的次数为:m*n*p。
矩阵连乘:多个矩阵相乘,它满足结合律,故计算矩阵连乘有许多不同的计算次序,不同的计算次序也会导致计算量(数乘次数)的不同。例如:
有三个矩阵A1:10*20,A2:20*40,A3:40*30,则A1*A2*A3有两种计算次序:
(一)、(A1*A2)*A3,则计算量(数乘次数)为 :10*20*40+10*40*30=20000.
(二)、A1*(A2*A3),则计算量(数乘次数)为:20*40*30+10*20*30=30000.

由此可见对于连乘的矩阵较多的情况,计算次序对计算量的影响很大。矩阵连乘要解决的问题就是,对于给定的合法连乘积A1*A2*…*An,怎么求出最小的计算量(最优值)以及满足最优值的乘法次序(最优解)。
我们记Ai*…*Aj为A[i,j],记第i个矩阵的维数为Pi-1*Pi。则如果A[1,n]即(整个矩阵连乘积)的计算次序最优,那么A[1,k]和A[k+1,n]的计算次序也是最优的。即具有最优子结构性质。
记m[i][j]为计算A[i,j]所需要的最小计算量,则原问题最优解为m[1][n],由此写出状态转移方程:
m[i][j]=min(m[i][k]+m[k+1][j]+Pi-1*Pk*Pj).其中 i <= k < j。且边界为i=j时 m[i][j]=0.(此时为单个矩阵计算量为0)。
代码:

#include <iostream>
using namespace std;
const int N=10;
int p[7]={30,35,15,5,10,20,25};
//p[0]:第一个矩阵的行数
//p[1]:第一个矩阵的列数,第二个矩阵的行数
//p[2]:第二个矩阵的列数,第三个矩阵的行数 ....... 
int m[N][N]; 
int s[N][N];//s[i][j]表示以i为其实位置,j为终止位置的最优计算量的括号位置 

void MatrixChain(int n){//n为矩阵数量 
    for(int i=1;i<=n;i++){
        m[i][i]=0;//边界初始化 
    }

    for(int r=2;r<=n;r++){//r代表当前矩阵连乘序列的长度 
        for(int i=1;i<=n-r+1;i++){//i代表矩阵连乘序列的起始位置
            int j=i+r-1;//j代表矩阵连乘序列的最终位置 
            m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];//以i为括号值 
            s[i][j]=i;//记录括号位置i 
            for(int k=i+1;k<j;k++){//从i+1到j-1的括号位置,找最小 
                int 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 Traceback(int i,int j){
    if(i==j) return ;
    Traceback(i,s[i][j]);//递归打印k和k左边的
    Traceback(s[i][j]+1,j);//递归打印k右边的 
    cout<<"Mutiply A["<<i<<","<<s[i][j]<<"]"<<
    " and A["<<s[i][j+1]<<","<<j<<"]"<<endl;
} 

int main(){
    MatrixChain(6);
    for(int i=1;i<=6;i++){
        for(int j=1;j<=6;j++){
            if(i>j){
                cout<<"\t";
            }
            else{
                printf("%-8d",m[i][j]);
            }
        }
        cout<<endl;
    }
    cout<<m[1][6]<<endl;
    Traceback(1,6);
    return 0;   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值