Fork me on GitHub

【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),然后你对张三的所有命令才能达到你的预想,不会叫错人 。

 

 




  
posted @ 2015-03-16 17:41  郑斌blog  阅读(770)  评论(0编辑  收藏  举报