• 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
  • 相关阅读:
    ag-Grid Enterprise v28.2.1 企业版注册版
    低成本IC上岸攻略—IC设计网课白嫖篇
    【路径规划-TSP问题】基于粒子群结合蚁群算法求解旅行商问题附matlab代码
    OSI与TCP/IP 5层协议
    Scala的一等公民和至简原则
    物理层课后作业
    【算法面试题汇总】LeetBook列表的算法面试题汇总---树题目及答案
    如何在前端应用程序中实现国际化(以英语为例)
    抽奖中的分布式锁应用
    学妹居然叫我帮她P证件照自拍,结果发现.........
  • 原文地址:https://blog.csdn.net/qq_19887221/article/details/125450923