ACM. HJ70 矩阵乘法计算量估算 ●●

8 篇文章 0 订阅
7 篇文章 0 订阅

HJ70 矩阵乘法计算量估算 ●●

描述

矩阵乘法的运算量与矩阵乘法的顺序强相关。
例如:
A是一个50×10的矩阵,B是10×20的矩阵,C是20×5的矩阵
计算ABC有两种顺序:((AB)C)或者(A(BC)),前者需要计算15000次乘法,后者只需要3500次。
编写程序计算不同的计算顺序需要进行的乘法次数。

数据范围:矩阵个数: 1 ≤ n ≤ 15 1\le n\le 15 1n15,行列数: 1 ≤ r o w i , c o l i ≤ 100 1\le row_i,col_i\le 100 1rowi,coli100,保证给出的字符串表示的计算顺序唯一。
进阶:时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( n ) O(n) O(n)

输入描述:

输入多行,先输入要计算乘法的矩阵个数 n,每个矩阵的行数,列数,总共 2n 的数,最后输入要计算的法则;
计算的法则为一个字符串,仅由左右括号和大写字母(‘A’~‘Z’)组成,保证括号是匹配的且输入合法!

输出描述:

输出需要进行的乘法次数

示例

输入:
3
50 10
10 20
20 5
(A(BC))
输出:
3500

题解

1. 栈

首先要知道矩阵运算的过程和规律,

[ m , n ] [m, n] [m,n] 表示 m m m n n n 列的矩阵,以 [ m , n ] ∗ [ n , p ] [m, n] * [n, p] [m,n][n,p] 为例进行矩阵乘法规则说明:

  • 第一个矩阵取一行,第二个矩阵取一列,计算时是对应相乘,有 n n n 次乘法。
  • 还是第一个矩阵刚参加运算的那行,第二个矩阵的所有列(共 p 列),会有 n ∗ p n*p np 次乘法
  • 第一个矩阵的所有行(共 m m m 行)参加运算,共会有 n ∗ p ∗ m n*p*m npm 次乘法运算。
  • 得出 [ m , n ] ∗ [ n , p ] [m, n] * [n, p] [m,n][n,p] 共会有 n ∗ p ∗ m n*p*m npm 次乘法运算,运算后得到的矩阵为 [ m , p ] [m, p] [m,p]

因此,我们可以利用栈来进行判断和运算,遍历字符串,

  • 当字符为左括号时,跳过;
  • 当字符为字母时,转化为对应的矩阵大小加入栈内;
  • 当字符为右括号时,取出栈顶的两个矩阵进行运算,并将运算后得到的矩阵大小压入栈中。

可知字符串的长度为 n + 2 * ( n - 1),n 为矩阵个数。

  • 时间复杂度:O(N),遍历所有矩阵或规定计算顺序的字符串的代价,其中N为矩阵的数量
  • 空间复杂度:O(N),存储矩阵数据的空间大小,和其他一些等代价的空间申请的大小

在这里插入图片描述

#include <iostream>
#include <vector>
#include <map>
#include <stack>
using namespace std;

int main(){
    int n;
    while(cin >> n){
        vector<vector<int>> m(n, vector<int>(2, 0));  // m[i][0] 表示行
        for(int i = 0; i < n; ++i){
            cin >> m[i][0] >> m[i][1];
        }
        stack<vector<int>> st;
        int ans = 0;
        for(int i = 0; i < 3*n-2; ++i){		// 字符串的长度为 n + 2*(n-1)
            char ch;
            cin >> ch;
            if(ch == '('){					// 左括号不处理
                continue;
            }else if(ch == ')'){			// 右括号,对头两个矩阵进行操作
                vector<int> a(2, 0);
                vector<int> b(2, 0);
                b = st.top();				// a * b
                st.pop();
                a = st.top();
                st.pop();
                ans += a[0] * a[1] * b[1];	// 计算次数为 a行 * a列 * b列
                st.emplace(vector<int>{a[0], b[1]});	// 将计算后的新矩阵大小压入栈内
            }else{
                st.emplace(m[ch-'A']);		// 字母,使对应的矩阵大小入栈
            }
        }
        cout << ans << endl;
    }
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值