矩阵链相乘的乘法次数

Description

设 A1, A2, …, An 为矩阵序列,Ai 是阶为 Pi − 1 × Pi 的矩阵 i = 1, 2, …, n.
试确定矩阵的乘法顺序,使得计算 A1 A2…An 过程中元素相乘的总次数最少.

Input

多组数据

第一行一个整数 n(1≤n≤300) ,表示一共有 n 个矩阵.

第二行 n + 1 个整数 P0, P1, …, Pn(1≤Pi≤100) ,第i个矩阵的行数为Pi − 1,列数为Pi.

Output

对于每组数据输出最少的元素乘法次数.

Sample Input

5
74 16 58 58 88 80
5
10 1 50 50 20 5

Sample Output

342848
3650
Hint

矩阵乘法规则

如果A是a×b的矩阵,B是b×c的矩阵,那么AB就是a×c的矩阵,所做的乘法次数为a×b×c

矩阵链乘法

给定一个矩阵链A1A2A3A4,要计算乘积,给这个矩阵链加上括号,来改变运算次序。如果矩阵链为(A1,A2,A3,A4),那么有如下5中加括号的方式:

(A1(A2(A3 A4)))
(A1((A2 A3)A4))
((A1 A2)(A3 A4))
((A1(A2 A3))A4)
(((A1 A2)A3)A4)

改变矩阵的运算次序,能改变所做乘法的运算次数。比如说3个矩阵的链(A1,A2,A3),假设3个矩阵的维数分别为10×100,100×5,5×50。按照((A1,A2)A3)的次序来计算,需要10×100×5+10×5×50=7500次乘法。

但如果按照(A1(A2,A3))的次序来计算,则需要100×5×50+10×100×50=75000次乘法,慢了10倍。可以看出矩阵链中不同的运算顺序会导致运算次数有很大的差异。

矩阵链乘法问题

矩阵链乘法问题就是寻找一个最佳的运算次序,使所做的乘法次数最小。
p[n+1]:表示n个矩阵的维度,其中矩阵Ai的维度为(pi-1)*pi

问题分析

一个序列如果只有一个矩阵,则只有一种方式加全部括号。

如果有两个或两个以上的矩阵,则必然可以看做两个子序列的乘积,且这两个子序列又可以分解成更小的两个子序列的乘积(两个矩阵相乘的运算次数看前面)。

我们用cost(i,j)表示序列Ai…Aj在最优加全部括号时的标量乘积次数,则
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;

const int size = 1500;
int num;           //矩阵个数
int p[size];       //矩阵规模的记录
int m[size][size]; //记录最优值

void matrixchain()
{
    int i, r, j, k, q;
    //从两个矩阵链开始,逐次添加矩阵链的长度(r表示矩阵链的长度)
    for (r = 2; r <= num; r++)
    {
        //解决方案优先选取先左边的矩阵
        for (i = 1; i <= num - r + 1; i++) // i值为左端点位置,取值不能大于num-r+1
        {
            j = i + r - 1; // j为右端点位置
            m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];
            //计算代价,图个代价等于划分位置两边的矩阵代价,加上两矩阵合并代价
            for (k = i + 1; k < j; k++) //遍历全部可能的划分点k,计算出最优的划分方案
            {
                q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; //计算划分的代价
                if (q < m[i][j])
                {
                    m[i][j] = q; //将最优的值q保存在m[i][j]中
                }
            }
        }
    }
    cout << m[1][num] << endl;
}

int main()
{
    while (scanf("%d", &num) != EOF)
    {
        for (int i = 0; i <= num; i++)
        {
            cin >> p[i];
        }
        matrixchain();
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值