FZU1061 矩阵连乘 C++STL应用

 Problem 1061 矩阵连乘

 Problem Description

给定n个矩阵{A1,A2,...,An},考察这n个矩阵的连乘积A1A2...An。由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序,这种计算次序可以用加括号的方式来确定。

矩阵连乘积的计算次序与其计算量有密切关系。例如,考察计算3个矩阵{A1,A2,A3}连乘积的例子。设这3个矩阵的维数分别为10*100,100*5,和5*50。若按(A1A2)A3计算,3个矩阵连乘积需要的数乘次数为10*100*5+10*5*50 = 7500。若按A1(A2A3)计算,则总共需要100*5*50+10*100*50 = 75000次数乘。

现在你的任务是对于一个确定的矩阵连乘方案,计算其需要的数乘次数。

 Input

输入数据由多组数据组成。每组数据格式如下:
第一行是一个整数n (1≤n≤26),表示矩阵的个数。
接下来n行,每行有一个大写字母,表示矩阵的名字,后面有两个整数a,b,分别表示该矩阵的行数和列数,其中1<a,b<100。
第n+1行是一个矩阵连乘的表达式,由括号与大写字母组成,没有乘号与多余的空格。如果表达式中没有括号则按照从左到右的顺序计算,输入的括号保证能够配对。

 Output

对于每组数据,输出仅一行包含一个整数,即将该矩阵连乘方案需要的数乘次数。如果运算过程中出现不满足矩阵乘法法则的情况(即左矩阵列数与右矩阵的行数不同),则输出“error”。

 Sample Input

3A 10 100B 100 5C 5 50A(BC)

 Sample Output

75000

当作写设计一类的程序吧。


const  int  Max_N = 108 ;
struct Mat{   /*矩阵*/
       int row ;
       int col ;
       char logo ;
       Mat(){}
       Mat(int r , int c , char lg):row(r),col(c),logo(lg){}
       friend bool operator == (const Mat &A , const Mat &B){
            return A.row == B.row && A.col == B.col  ;
       }
};

Mat  mat[40] ;

const Mat Leftkuohao = Mat(-100000 , -100000 , '(') ; /*标记(括号*/


/*形如ABCD ,也就是()里面的乘法,返回和,非法返回-1 ,并保存最后结果矩阵rest */
int  Gao(vector<Mat> &List  , Mat &rest){  
     int i , j  , ans = 0  , now , re ;
     for(i = 1 ; i < List.size() ; i++){
          if(List[i].row !=  List[i-1].col)
              return -1 ;
          ans += List[0].row * List[i].row * List[i].col ;
     }
     rest = Mat(List[0].row , List[List.size()-1].col , '*') ;
     return ans ;
}

vector<Mat> GetList(stack<Mat> &st){   /*遇到)时,在栈中找出与之匹配(中间的链,并翻转逆序*/
      vector<Mat> ans ;
      ans.clear() ;
      while(! st.empty()){
         if(st.top() == Leftkuohao){
                st.pop() ;
                break ;
         }
         else{
                ans.push_back(st.top()) ;
                st.pop() ;
         }
     }
     std::reverse(ans.begin() , ans.end()) ;
     return ans ;
}

int  Ans(string s){   /*括号匹配,栈的应用*/
     int i , j  , ans = 0 , sum ;
     stack<Mat> st ;
     vector<Mat> now ;
     Mat rest ;
     for(i = 0 ; i < s.length() ; i++){
         if(s[i] == '(')
            st.push(Leftkuohao) ;
         else if(s[i] == ')'){
            now = GetList(st) ;
            sum = Gao(now , rest) ;
            if(sum == -1)
                return -1 ;
            ans += sum ;
            st.push(rest) ;
         }
         else
            st.push(mat[s[i] - 'A']) ;
     }
     now = GetList(st) ;
     ans += Gao(now , rest) ;
     return ans ;
}

int  main(){
     int r , c  , n ;
     string s , mt;
     while(cin>>n){
        for(int i = 0 ; i < n ; i++){
            cin>>mt>>r>>c ;
            mat[mt[0] - 'A'] = Mat(r , c , mt[0]) ;
        }
        cin>>s  ;
        int ans  = Ans(s) ;
        if(ans == -1)
           puts("error")   ;
        else
           printf("%d\n" , ans) ;
     }
     return 0 ;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值