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行是一个矩阵连乘的表达式,由括号与大写字母组成,没有乘号与多余的空格。如果表达式中没有括号则按照从左到右的顺序计算,输入的括号保证能够配对。
第一行是一个整数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 ;
}