输入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;
}
}
总结:
- 考察了矩阵乘法的知识
- 在括号等成对出现的数据结构前考虑用栈