给定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次数乘。
现在你的任务是对于一个确定的矩阵连乘方案,计算其需要的数乘次数。
当作写设计一类的程序吧。
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 ; }