30行代码AC——例题6-3 矩阵链乘(Maxtrix Chain Multiplication, UVa 442)——解题报告

励志用尽量少的代码做高效的表达。


题目(提交)链接→UVa-442


储备知识:

矩阵相乘次数:

在这里插入图片描述
如图:A矩阵*B矩阵得到C矩阵。 C矩阵中元素个数=A矩阵行数*B矩阵列数。得到C矩阵中任意元素都需要运算A矩阵的列数次。
因此,总运算次数为:A矩阵行数*B矩阵列数*A矩阵列数(B矩阵行数)=2*2*3=12次。

同理:求A(BC)的运算次数:
设BC矩阵相乘后得D矩阵。
则总次数=BC相乘后的次数+AD相乘后的次数。


思路:

正常的解析表达式类型题直接用字母运算,但本题每个字母对应不同的矩阵。因此本题实质为解析表达式+字符映射矩阵。采用stack<int>s存储字母(解析表达式);采用map<char, pair<int, int>>m 分别存储字符、矩阵的行和列(字母映射矩阵)
实现过程:遍历输入序列,若为字母则压入栈。 若为右括号,则连续弹出两个栈顶元素做运算, 乘法次数累加至sum中。 本次运算完成后, 建立关于map的新字母映射,存入map(map有去重功能,如果不是新字母映射,会自动删去), 同时将新字母压入栈。 继续遍历。

注意:

1、栈弹出的顺序与输入的顺序相反,判断行列相等时不要弄反了。
2、因为输入保证合法,括号无需入栈。

代码:

#include<bits/stdc++.h>							//万能头文件
using namespace std;
int main() {
	map<char,pair<int, int> >m;
	int n; cin >> n; int n1 = n;
	while(n--) {									//构建map映射
		char ch; cin >> ch; 						//输入字母
		cin >> m[ch].first >> m[ch].second;			//输入矩阵的行、列数
	} 
	string s; while(cin >> s) {						//输入表达式
		bool flag = false;							//做最后的输出判断。
		stack<int>ss; 
		int len = s.length(), sum = 0;				//sum为乘法次数累加
		for(int i = 0; i < len; i++) {				//遍历表达式
			if(isalpha(s[i])) ss.push(s[i]);		//如果是字母,则压入栈 
			else if(s[i] == ')') {					//若为右括号,则弹出两个字母做运算 
				char b = ss.top(); ss.pop();		
				char a = ss.top(); ss.pop();
				if(m[b].first == m[a].second) {		//运算过程 
					sum += m[a].first*m[b].second*m[a].second;	//计算乘法次数 
					m['A'+n1].first = m[a].first;	//建立新字母,新映射 
					m['A'+n1].second = m[b].second;	
					ss.push((char)('A'+n1++));		//新字母入栈 
				} else { cout << "error\n"; flag = !flag; break; }
			}
		}
		if(!flag) cout << sum << '\n';
	}
	return 0;
} 

收获:

1、对栈解“解析表达式”更熟练。
2、对map映射运用更加灵活。


择苦而安,择做而乐。虚拟现实终究比不过真实精彩之万一。

发布了97 篇原创文章 · 获赞 104 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43899069/article/details/104834457