紫书刷题进行中,题解系列【GitHub|CSDN】
例题6-3 UVA442 Matrix Chain Multiplication(39行AC代码)
题目大意
求矩阵在不同乘法顺序下的乘法次数,假设矩阵A:a*b,矩阵B:b*c,那么A*B的乘法总次数为a*b*c
思路分析
矩阵链相乘是动态规划中的典例,可快速计算相乘次数最少的相乘方式,这里比较简单,只需求给定顺序的相乘次数,主要在于括号处理,可用栈轻松实现。
由题目给出的EBNF可知,每个括号内部一定只有两个矩阵,因此同一级括号内部个数确定,无需在存储括号。即遇到矩阵压栈,遇到右括号将弹出两个栈顶,计算后再次压入,遇到左括号不处理。
若是每个括号内矩阵个数未知,则必须根据括号来标记同一层级的位置
AC代码(C++11,stack)
#include<bits/stdc++.h>
using namespace std;
int n, a, b;
char ch;
map<char, pair<int,int> > mp; // 矩阵->(行数,列数)
int simu(string s) { // 模拟相乘过程,错误返回-1,否则返回次数
int ans = 0;
stack<pair<int,int> > stk; // 矩阵栈,第一二维
bool isErr=false; // 标记是否有错误
for (auto c : s) {
if (isalpha(c)) stk.push(mp[c]); // 矩阵
if (c == ')') { // 出栈计算
auto p1 = stk.top(); stk.pop();
auto p2 = stk.top(); stk.pop();
if (p2.second != p1.first) { // 错误
isErr = true;
break;
}
ans += p2.first*p2.second*p1.second; // 运算次数
stk.push({p2.first, p1.second}); // 重新压入
}
}
return ans = (isErr) ? -1 : ans;
}
int main() {
scanf("%d", &n);
while (n --) {
getchar();
scanf("%c %d %d", &ch, &a, &b);
mp[ch] = {a,b};
}
string s;
while (cin >>s) {
int ans = simu(s);
if (ans == -1) puts("error");
else printf("%d\n", ans);
}
return 0;
}