【UVa-442】矩阵链乘——简单栈练习
题目描述:
输入n个矩阵的维度和一些矩阵链乘表达式,输出乘法的次数。如果乘法无法进行,输出error。
Sample Input
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))
Sample Output
0 0 0 error 10000 error 3500 15000 40500 47500 15125
【题目分析】
用一个栈来完成:遇到字母时入栈,遇到右括号时出栈并计算,然后出栈输出结果。
矩阵链乘规则:
A是50*10的,B是10*20的,C是20*5的,则(A(BC))的乘法次数为10*20*5(BC的乘法次数) + 50*10*5((A(BC))的乘法次数) = 3500。
【代码】
1 #include<cstdio> 2 #include<stack> 3 #include<iostream> 4 #include<string> 5 using namespace std; 6 7 //定义结构体 8 struct Matrix { 9 int a,b; 10 //构造函数 11 Matrix(int a = 0 , int b = 0) : a(a),b(b){} 12 } m[26];//声明Matrix实例 13 14 //定义栈 15 stack<Matrix> s; 16 17 int main(){ 18 19 //输入矩阵名和其维度 20 int n; 21 cin >> n; 22 for(int i = 0; i < n;i++) 23 { 24 string name; 25 cin >> name; 26 int k = name[0] - 'A';//计算元素与'A'阿斯卡码值的差 27 cin >> m[k].a >> m[k].b;//通过预定义的结构体,获得输入的矩阵维度 28 } 29 30 //输入矩阵链乘表达式 31 string expr; 32 while(cin >> expr) 33 { 34 int len = expr.length(); 35 bool error = false; 36 int ans = 0; 37 for(int i = 0; i < len; i++){ 38 if(isalpha(expr[i])) s.push(m[expr[i] - 'A']);//判断当前元素是否为字母,则将其对应的矩阵维度压入栈 39 else if(expr[i] == ')'){ 40 //取出栈顶元素后,并删除 41 Matrix m2 = s.top(); s.pop(); 42 Matrix m1 = s.top(); s.pop(); 43 if(m1.b != m2.a){error = true; break;}//判断是否符合链乘规则 44 ans += m1.a * m1.b * m2.b; 45 s.push(Matrix(m1.a,m2.b)); 46 //链乘规则: A,B,C; (A(BC)) = A(BC) + BC; 47 } 48 } 49 if(error) printf("error\n"); else printf("%d\n",ans); 50 } 51 return 0; 52 }
【总结】
1.结构体:
自定义数据类型
1 /*在c++中struct和类的区别在于struct不能有方法,所有成员是public的*/ 2 struct Movie/*可以指定类型名也可以不指定*/ 3 { 4 //成员都是public 5 int ID; 6 string Name; 7 } movie; //可以在声明struct的时候声明一个struct实例
2.构造函数:
1 //每一个对象必须要有相应的构造函数 2 //若没有显示定义构造函数,系统默认缺省的构造函数。 3 class A{ 4 float x,y; 5 public: 6 A() {} //隐含的缺省的构造函数 7 void Print(void) {cout << x << "\n" << y <<endl;} 8 }; 9 //只允许这样定义对象 10 A a1,a2;
3.C++类构造函数初始化列表
1 class CExample { 2 public: 3 int a; 4 float b; 5 //构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。 6 //显示的初始化类的成员 7 //构造函数初始化列表 8 CExample(): a(0),b(8.8) 9 {} 10 11 //对类的成员赋值,并没有进行显式的初始化 12 //构造函数内部赋值 13 CExample() 14 { 15 a=0; 16 b=8.8; 17 } 18 };
4. using namespace std;
std 是一个命名空间不同的命名空间可以有相同的类名被定义。
比如A B两个班都有叫张三的人,你要使用A班的张三,必然要先指名是A班这个名字空间(namespace),然后你对张三的所有命令才能达到你的预想,不会叫错人 。
梦想要一步步来!