当前位置 博文首页 > 爱新觉罗?炒饭的博客:矩阵连乘问题(动态规划)

    爱新觉罗?炒饭的博客:矩阵连乘问题(动态规划)

    作者:[db:作者] 时间:2021-07-07 15:34

    题目描述:
    给定n个矩阵{A1,A2,…,An},其中,Ai与Ai+1是可乘的,(i=1,2 ,…,n-1)。用加括号的方法表示矩阵连乘的次序,不同的计算次序计算量(乘法次数)是不同的,找出一种加括号的方法,使得矩阵连乘的次数最小。在这里插入图片描述算法:最优子结构如下:假设A1A2...An的一个最优加括号把乘积在Ak和Ak+1间分开,则前缀子链A1...Ak的加括号方式必定为A1...Ak的一个最优加括号,后缀子链同理。一开始并不知道k的确切位置,需要遍历所有位置以保证找到合适的k来分割乘积。](https://img-blog.csdnimg.cn/20210329163250548.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ3Mjk5NDIx,size_16,color_FFFFFF,t_70)构造递归解:设m[i,j]为矩阵链Ai…Aj的最优解的计算花费代价在这里插入图片描述在这里插入图片描述
    代码一:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    int m[100][100];
    int s[100][100];
    void MatrixChain(int *p,int n)//求最优值
    {
        for(int i=0;i<=n;i++)
            m[i][i]=0;
        for(int r=2;r<=n;r++)
        {
            for(int i=1;i<=n-r+1;i++)
            {
                int j=i+r-1;
                m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
                s[i][j]=i;
                for(int k=i+1;k<j;k++)
                {
                    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]);
        Traceback(s[i][j]+1,j);
        cout<<"Multipy A"<<i<<","<<s[i][j];
        cout<<" and A"<<(s[i][j]+1)<<","<<j<<endl;
    }
    int main()
    {
       int p[]={30,35,15,5,10,20,25};
       MatrixChain(p,6);
       cout<<m[1][6]<<endl;
       Traceback(1,6);
       return 0;
    }
    

    代码二:
    在这里插入图片描述

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    int m[100][100];
    int s[100][100];
    int p[7]={30,35,15,5,10,20,25};
    int LookupChain(int i,int j)
    {
        if(m[i][j]>0)    //表示相应的子问题已经被计算过了,直接返回结果即可
            return m[i][j];
        if(i==j)
            return 0;
        int u=LookupChain(i,i)+LookupChain(i+1,j)+p[i-1]*p[i]*p[j];
        s[i][j]=i;
        for(int k=i+1;k<j;k++)
        {
            int t=LookupChain(i,k)+LookupChain(k+1,j)+p[i-1]*p[k]*p[j];
            if(t<u)
            {
                u=t;
                s[i][j]=k;
            }
        }
        m[i][j]=u;
        return u;
    }
    int MemoizeMatrixChain(int n)//求最优值
    {
        for(int i=1;i<=n;i++)
            for(int j=i;j<=n;j++)
                m[i][j]=0;
        return LookupChain(1,n);
    }
    void Traceback(int i,int j)//求最优解
    {
        if(i==j)
           return;
        Traceback(i,s[i][j]);
        Traceback(s[i][j]+1,j);
        cout<<"Multipy A"<<i<<","<<s[i][j];
        cout<<" and A"<<(s[i][j]+1)<<","<<j<<endl;
    }
    int main()
    {
       MemoizeMatrixChain(6);
       cout<<m[1][6]<<endl;;
       Traceback(1,6);
       return 0;
    }
    
    
    
    cs