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


    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    【vue 首屏加载优化】
    不知道怎么把英文文档翻译成中文?手把手教你怎么操作
    【C++】类和对象 — 日期类的实现 运算符重载 初始化列表 友元(下篇)
    Ubuntu设置静态IP地址的几种方法
    Spring-Cloud-Openfeign如何支持数据压缩?
    2311C++抽象工厂
    【设计模式】过滤器模式(Filter Pattern)
    网课查题公众号如何搭建查题系统
    Python中,如何读取和写入文件?
    mysql中的各种日志文件redo log、undo log和binlog
  • 原文地址:https://blog.csdn.net/qq_19887221/article/details/125450923