UVa 442 矩阵链乘 (Matrix Chain Multiplication)

输入n个矩阵的维度和一些矩阵链乘的表达式,输出乘法的次数,如果乘法无法进行,输入error
假定A是 m * n 矩阵 B 是 n * p 矩阵 那么 AB 是 m * p矩阵,相信学过线性代数的都不陌生
乘法的次数 为 m * n * p 第一个矩阵的每个数都要和第二个矩阵的

在这里插入图片描述 在这里插入图片描述
在这里插入图片描述

A 矩阵的每一行都要和B矩阵的每一列对应相乘
这里的乘法次数是 m * p
又A有n行 因此乘法次数是 n * m * p

要点:

  • SecondPart = Line { Line }
  • Line = Expression
  • Expression = Matrix | “(” Expression Expression “)”
  • Matrix = “A” | “B” | “C” | … | “X” | “Y” | “Z”

主要是这里的expr 只有可能是一个matrix或者(matrix matrix)
换句话说不可能一个括号里面包括三个矩阵
因此这里可以遇到右括号就计算左边的值,因为有右括号的话,一定中间有两个矩阵(可能是算过后的)可以计算了

扩展:(单纯考虑这道题目的不要看)
例如 (A(BC)) 遇到右括号算 D = BC 然后是(AD) 然后再算
这题如果稍微改一些条件就不可以只用栈,不过似乎可以考虑使用栈 + 队列的双重结构
我们考虑:
(A(BCD))
定义bool seeAlpha = false;
1.if(seeAlpha == false && 目前这个是字母)
创建一个队列 seeAlpha = true;
2.如果是字母就最新的队列
3.如果遇到 seeAlpha == true 且这个不是字母的话
将队列入栈
并将seeAlpha定义为 false
这样我们得到了一个 A BCD 的栈队列
4.遇到右括号 取出队列
计算BCD 的值 先算 E = BC 然后再算 F = ED 个数为1个的时候出来
加入目前的栈的头部的队列
然后遇到右括号再取出来…
我们测试其他情况是否想法有效
(((A(BC))((DE)(FG)))
1.A
2.BC
3.计算M1 = BC
4.计算M2= AM1
3.DE
4.FG
5.M3 = DE //此时的栈是 M2M3 ; 空 ;
6.M4 = FG //此使的栈是 M2M3 ; M4
7. 栈是 M2M3M4
这个时候会计算 变成 最后的 M5 = M2 * M3 ;
M6 = M5 * M4
最后剩下一个M6 这个时候的ANS也得到了
似乎可行,但没有进行更加严密的判断

附上这题的代码:

#include<iostream>
#include<stack>
#include<string>
using namespace std;

struct Matrix {
    int a, b;
    Matrix(int a = 0,int b = 0):a(a),b(b) {}
}m[26];

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int n;
    cin >> n;
    while(n--) {
        char ch;
        cin >> ch;
        int k = ch - 'A';
        cin >> m[k].a >> m[k].b;
    }
    string expr;
    while(cin >> expr) {
        int ans = 0;
        stack<Matrix> s;
        bool error = false;
        for(int i = 0; i < expr.length(); i++){
            if(isalpha(expr[i])){s.push(m[expr[i] - 'A']);}
            else if(expr[i] == ')') {
                Matrix m1 = s.top(); s.pop();
                Matrix m2 = s.top(); s.pop();
                if(m1.a != m2.b) {error = true; break;}
                ans += m2.a * m2.b * m1.b;
                s.push(Matrix(m2.a, m1.b));
            }
        }
        if(error) cout << "error" << endl;
        else cout << ans << endl;
    }
}

总结:

  1. 考察了矩阵乘法的知识
  2. 在括号等成对出现的数据结构前考虑用栈
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值