题目:
输入n个矩阵的维度和一些矩阵的链乘表达式,输出乘法的次数。如果乘法无法进行,输出error。假定A是m*n矩阵,B是n*p的矩阵,那么A*B是m*p的矩阵,乘法次数为m*n*p。如果A的列数不等于B的行数,则乘法无法进行。
例如,A是50*10的,B是10*20的,C是20*5的,则(A(BC))的乘法次数为10*20*5(BC的乘法次数)+50*10*5=3500。
输入:
3
A 50 10
B 10 20
C 20 5
(A(BC))
输出:
3500
分析:
本题的关键是解析表达式。表达式比较简单,可以用一个栈来完成:遇到大写字母"A~Z"时进行入栈操作,遇到右括号“)”时出栈并计算,然后将结果入栈。括号可看做入栈、出栈的标志符,无需将括号入栈,由此可将问题得到进一步简化。
package uva;
import java.util.*;
/**
* @author Perfwxc
* 创建矩阵Matrix类
* a代表矩阵的行数
* b代表矩阵的列数
*/
class Matrix{
int a,b;
Matrix(int a,int b){
this.a = a;
this.b = b;
}
}
public class Uva442 {
public static void main(String[] args){
//创建Matrix类型的栈并初始化,这里与C语言有所不同,不进行初始化操作对s赋值会导致空指针错误
Stack<Matrix> s = new Stack<Matrix>();
//创建Matrix类型数组,题目限定(1 <= n <= 26)
Matrix m[] = new Matrix[26];
int n;
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for(int i =0; i < n; i ++){
//Java无法直接输入char类型数据,故先输入String类型数据再使用charAt()方法得到char类型数据
String sname;
sname = sc.next();
char name;
name = sname.charAt(0);
//name - 'A'操作相当于为输入的矩阵添加索引
int k = name - 'A';
m[k] = new Matrix(0,0);
//确定矩阵的行数a
m[k].a = sc.nextInt();
//确定矩阵的列数b
m[k].b = sc.nextInt();
}
//expr为待处理的矩阵运算表达式
String expr;
while(sc.hasNext()){
expr = sc.next();
int len = expr.length();
boolean error =false;
//ans表示需要进行乘法运算的总次数
int ans = 0;
for(int i =0; i < len; i ++){
//使用Character.isLetter()函数判断字符串的第i个字符是否为字母,若是字母,为其加入索引后进行入栈操作
if(Character.isLetter(expr.charAt(i))) s.push(m[expr.charAt(i)-'A']);
//当遇到")"时进行出栈并运算
else if(expr.charAt(i) == ')'){
//取栈顶元素后出栈
Matrix m2 = s.peek(); s.pop();
Matrix m1 = s.peek(); s.pop();
//判断矩阵m1的列数与矩阵m2的行数是否相等,若不相等,则无法进行矩阵运算
if(m1.b != m2.a){
error = true;
break;
}
//两矩阵[m,n],[n,p]相乘,所需乘法操作数为m*n*p
ans += m1.a * m1.b * m2.b;
//运算完毕后,将运算结果入栈
s.push(new Matrix(m1.a,m2.b));
}
}
if(error)
System.out.println("error");
else
System.out.println(ans);
}
}
}