算法分析与设计——以ACM程序设计为例——P28矩阵相乘次数
解决此题,须知道三项矩阵相乘基本知识:A*B 矩阵相乘
1:需满足A的列数等于B的行数。
2:矩阵相乘次数=A的行数 *B的行数 *B的列数
3:矩阵结果的行数=A的行数,列数=B的列数
算法描述:
1:构造数据结构:
结点:代表一个矩阵的行列数
struct Node {
int row, col;
};
映射:将矩阵名称与相应行列数联系起来
map<char, Node> matrix;
堆栈:用来将输入的表达式中的矩阵(名称)压入,方便计算
stack array;
2输入相关数据
cin >> n;
for (i = 0; i < n; i++) { //输入名称和相应的行列数
cin >> Name;
cin>> matrix[Name].row >> matrix[Name].col;
}
采用先输入名称,接着利用映射输入相关行列数(曾经试过一次性全部输入,但vs2019好像有点问题,你运气好的话应该也可以一次性输入)
3 计算每一个表达式
输入exp要计算的表达式(须有括号,否则无法计算)
分三种情况
a:如果exp[i]是矩阵(名称),直接将它(或者说映射出来的行列数)压入array堆栈中(由此可见array中的矩阵(字母)是原表达式中的倒序,如(AB),在堆栈中从头到尾是BA,这很重要,否则答案会一直错误,别问我怎么知道的)
b:exp[i]==’(‘时,很简单,直接continue省略他,进入下一层循环。
c:exp[i]=’)'时,事儿最多,需要做的是,弹出array栈顶两个结点(比如先弹出a,后弹出b),并进行相乘,规则和上面一开始讲的一样,不再赘述,容易出错的是,计算时应按b*a来算(具体原因请看a中括号部分,因为这个笔者曾被气得xxx),如果满足b的列数等于a的行数,则将矩阵相乘次数记录下来(不等,直接break)。矩阵相乘的新矩阵行数列数(计算方法见最上面三个基本知识)压入堆栈中。
执行到表达式最后一个字符时,将计算总数count输出。最后大功告成!!!
#include<iostream>
#include<map>
#include<stack>
using namespace std;
struct Node {
int row, col;
};
map<char, Node> matrix; //将矩阵名称与相应行列数进行映射
int main() {
int n, i;
char Name;
string exp;
cin >> n;
for (i = 0; i < n; i++) { //输入名称和相应的行列数
cin >> Name;
cin>> matrix[Name].row >> matrix[Name].col;
}
while (cin>>exp)
{
stack<Node> array; //用堆栈记录所有矩阵行数和列数
int count = 0;
for (i = 0; i < exp.size(); i++) {
if (exp[i] == '(')continue;
else if (exp[i] == ')')
{
Node a = array.top();
array.pop();
Node b = array.top();
array.pop();
if (b.col != a.row) {
cout << "error" << endl; break; }
count += b.row * a.col * a.row;
Node tmp = { b.row,a.col };
array.push(tmp);
}
else {
array.push(matrix[exp[i]]);
}
}
if (i == exp.size())cout << count << endl;
}
return 0;
}
输入样例:
9
A 50 10
B 10 20
C 20 5
D 30 35
E 35 15
F 15 5
G 5 10
H 10 20
I 20 25
A
B
C
(AA)
(AB)
(AC)
(A(BC))
((AB)C)
(((((DE)F)G)H)I)
(D(E(F(G(HI)))))
((D(EF))((GH)I))