UVA442 Matrix Chain Multiplication

矩阵链乘 Matrix Chain Multiplication

题目描述

​ 假设你必须评估一种表达形如 ABCDE,其中 A,B,C,D,E是矩阵。既然矩阵乘法是关联的,那么乘法的顺序是任意的。然而,链乘的元素数量必须由你选择的赋值顺序决定。

​ 例如,A,B,C分别是 50 * 10 ,10 * 20 和 20 * 5 的矩阵。现在有两种方案计算 A * B * C ,即(A * B) * C 和 A*(B * C)。
第一个要进行15000次基本乘法,而第二个只进行3500次。

​ 你的任务就是写出一个程序判定以给定的方式相乘需要多少次基本乘法计算。

输入格式

​ 输入包含两个部分:矩阵和表达式。
输入文件的第一行包含了一个整数 n(1 ≤ \leq n ≤ \leq 26), 代表矩阵的个数。接下来的n行每一行都包含了一个大写字母,说明矩阵的名称,以及两个整数,说明行与列的个数。
第二个部分严格遵守以下的语法:

SecondPart = Line { Line }
Line = Expression
Expression = Matrix | “(” Expression Expression “)”
Matrix = “A” | “B” | “C” | … | “X” | “Y” | “Z”

输出格式

​ 对于每一个表达式,如果乘法无法进行就输出 " error "。否则就输出一行包含计算所需的乘法次数。

样例 #1

样例输入 #1

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))

样例输出 #1

0
0
0
error
10000
error
3500
15000
40500
47500
15125

题目分析

这道题考察 栈 这种数据结构,类似于表达式求值.
另外分析题目可知,矩阵相乘需要两两配对,不同的求值顺序,其乘法次数不一定相同,所以题目给出的输入有一个特点,就是任意一对括号内必有一对矩阵
解题思路:
这里的矩阵表示可以使用c++提供的二元组pair,或者自定义
这里自定义一个数据结构Matrix包含矩阵的行和列.
使用map来记录符号和对应的矩阵.
使用stack来进行算法设计.

#include <iostream>
#include <stack>
#include <map>
#include <string>

using namespace std;

typedef struct Matrix{
	int rows;
	int cols;
	Matrix(){
	}
	Matrix(int rows, int cols):rows(rows), cols(cols){
	}
}Matrix;

map<string, Matrix> vars;

int compute(string& expression);

int main(int argc, char **argv){
	int n = 0;
	cin >> n;
	for(int i = 0; i < n; i++){
		string name;
		int rows;
		int cols;
		cin >> name >> rows >> cols;
		vars[name] = Matrix(rows, cols);
	}
	string expression;
	while(cin >> expression){
		int result = compute(expression);
		if(result == -1){
			cout << "error" << endl;
		}else{
			cout << result << endl;
		}
	}
	return 0;
}

int compute(string& expression){
	stack<string> symbols;
	int result = 0;
	int length = expression.length();
	if(length == 1){
		return result;
	}
	for(int i = 0; i < length; i++){
		string tmp = string(1, expression[i]);
		if(tmp == "("){
			symbols.push(tmp);
		}else if(tmp == ")"){
			string m[2];
			for(int j = 0; j < 2; j++){
				m[j] = symbols.top();
				symbols.pop();
			}
			symbols.pop();
			if(vars[m[1]].cols != vars[m[0]].rows){
				return -1;
			}
			Matrix right = vars[m[0]];
			Matrix left = vars[m[1]];
			result += left.rows * left.cols * right.cols;
			if(!symbols.empty()){
				Matrix mat = Matrix(left.rows, right.cols);
				string name = m[1]+m[0];
				vars[name] = mat;
				symbols.push(name);
			}else{
				return result;
			}
		}else{
			symbols.push(tmp);
		}
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值