0
点赞
收藏
分享

微信扫一扫

矩阵连乘问题-动态规划


问题描述:

给定n个矩阵:A1, A2, ... , An,其中Ai与Ai+1是可乘的,i = 1,2 ...,n-1。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。

递推关系:

m[i][j] =  0,                                                                 i = j;

           = m[i][k] + m[k][j] + p[i - 1] * p[k] * p[j];        i != j;

代码:

//测试样例
/*
输入
6
30 35 15 5 10 20 25
输出
((A1(A2A3))((A4A5)A6))
15125
*/
#include <bits/stdc++.h>
using namespace std;
int p[1010];
int m[1010][1010];
int s[1010][1010];
int n;
void Traceback(int i, int j)
{
    if(i == j)
    {
     cout << "A" << i;
     return;
    }
    else
    {
        cout << "(";
        Traceback(i, s[i][j]);
        Traceback(s[i][j] + 1, j);
        cout << ")";
    }
}
void MatrixChain()
{
    for(int i = 1; i <= n; ++i)
        m[i][i] = 0;
    for(int r = 2; r <= n; ++r)//注释1见下
        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(m[i][j] > t)
            {
                m[i][j] = t;
                s[i][j] = k;
            }
        }
    }
}
void Input()
{
    scanf("%d", &n);
    //矩阵的行数和列数
    for(int i = 0; i <= n; ++i)
        scanf("%d", &p[i]);
}
int main()
{
    Input();
    MatrixChain();
    Traceback(1, n);
    cout << endl;
    cout << m[1][n];
}

注释1:

很多同学(包括刚开始的我...)不理解第一个循环r,然后百度百度百度,终于找到了能理解的一篇博地址矩阵连乘详解。

具体的来说,动态规划是由低往上的,r 就表示一次连乘矩阵的个数,即:由两个矩阵的连乘逐渐到n个矩阵相乘。

另外改写了Traceback函数,使输出更易懂。

举报

相关推荐

0 条评论