POJ 2246 Matrix Chain Multiplication(栈)

题目来源:http://poj.org/problem?id=2246

Matrix Chain Multiplication

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 2643

Accepted: 1600

Description

Suppose you have to evaluate an expression like A*B*C*D*E where A,B,C,D and E are matrices. 
Since matrix multiplication is associative, the order in which multiplications are performed is arbitrary. However, the number of elementary multiplications needed strongly depends on the evaluation order you choose. 
For example, let A be a 50*10 matrix, B a 10*20 matrix and C a 20*5 matrix. 
There are two different strategies to compute A*B*C, namely (A*B)*C and A*(B*C). 
The first one takes 15000 elementary multiplications, but the second one only 3500. 

Your job is to write a program that determines the number of elementary multiplications needed for a given evaluation strategy. 

Input

Input consists of two parts: a list of matrices and a list of expressions. 
The first line of the input file contains one integer n (1 <= n <= 26),representing the number of matrices in the first part. The next n lines each contain one capital letter, specifying the name of the matrix, and two integers, specifying the number of rows and columns of the matrix. 
The second part of the input file strictly adheres to the following syntax(given in EBNF): 

SecondPart = Line { Line } 

Line       = Expression 

Expression = Matrix | "(" Expression Expression ")"

Matrix     = "A" | "B" | "C" | ... | "X" | "Y" | "Z"

Output

For each expression found in the second part ofthe input file, print one line containing the word "error" ifevaluation of the expression leads to an error due to non-matching matrices.Otherwise print one line containing the number of elementary multiplicationsneeded to evaluate the expression in the way specified by the parentheses.

Sample Input

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

SampleOutput

0
0
0
error
10000
error
3500
15000
40500
47500
15125

Source

Ulm Local 1996

--------------------------------------------------------------

思路

【题意】

给出若干矩阵的维度和含有括号的矩阵乘法表达式,计算每个表达式中数字乘法的次数

【题解】

括号匹配:典型栈的应用

用两个栈,一个操作数栈opnum,存储矩阵,一个操作符栈operand,存储左括号。

从左到右扫描表达式,

扫描到左括号,将左括号入栈operand;

扫描到矩阵,将该矩阵入栈opnum;

扫描到右括号,operand栈顶左括号出栈,opnum栈顶两矩阵出栈,两矩阵相乘的结果入栈opnum

 

对于本题,实际编程时,只需opnum栈即可。

-----------------------------------------------------

代码 

#include<iostream>
#include<fstream>
#include<vector>
#include<string>
using namespace std;

struct node {
	int x, y;
	char name;

	node(void){}
	node(char nn, int xx, int yy): x(xx), y(yy), name(nn){}
};

node ndlist[27];

int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin ("2246.txt");
	int n,i,len,ans;
	char ch;
	bool is_error = false;
	fin >> n;
	node nd;
	for (i=0; i<n; i++)
	{
		fin >> nd.name >> nd.x >> nd.y;
		ndlist[i] = nd;
	}
	string s;
	vector<node> opnum;								// 操作数栈
	vector<char> operand;							// 操作符(括号)栈
	while (fin >> s)
	{
		ans = 0;
		is_error = false;
		len = s.size();
		for (i=0; i<len; i++)
		{
			ch = s.at(i);
			if (ch == '(')
			{
				operand.push_back(ch);
			}
			else if (ch == ')')
			{
				operand.pop_back();
				if (opnum.size()>=2)
				{
					node nd2 = opnum.back();
					opnum.pop_back();
					node nd1 = opnum.back();
					opnum.pop_back();
					if (nd1.y != nd2.x)
					{
						cout << "error" << endl;
						is_error = true;
						break;
					}
					else
					{
						ans += nd1.x * nd1.y * nd2.y;
						opnum.push_back(node('*', nd1.x, nd2.y));
					}
				}
				else if (opnum.size() == 1)
				{
					opnum.pop_back();
				}
			}
			else
			{
				opnum.push_back(ndlist[ch-'A']);
			}
		}
		if (!is_error)
		{
			cout << ans << endl;
		}
	}
	fin.close();
#endif
#ifdef ONLINE_JUDGE
	int n,i,len,ans;
	char ch;
	bool is_error = false;
	cin >> n;
	node nd;
	for (i=0; i<n; i++)
	{
		cin >> nd.name >> nd.x >> nd.y;
		ndlist[i] = nd;
	}
	string s;
	vector<node> opnum;								// 操作数栈
	vector<char> operand;							// 操作符(括号)栈
	while (cin >> s)
	{
		ans = 0;
		is_error = false;
		len = s.size();
		for (i=0; i<len; i++)
		{
			ch = s.at(i);
			if (ch == '(')
			{
				operand.push_back(ch);
			}
			else if (ch == ')')
			{
				operand.pop_back();
				if (opnum.size()>=2)
				{
					node nd2 = opnum.back();
					opnum.pop_back();
					node nd1 = opnum.back();
					opnum.pop_back();
					if (nd1.y != nd2.x)
					{
						cout << "error" << endl;
						is_error = true;
						break;
					}
					else
					{
						ans += nd1.x * nd1.y * nd2.y;
						opnum.push_back(node('*', nd1.x, nd2.y));
					}
				}
				else if (opnum.size() == 1)
				{
					opnum.pop_back();
				}
			}
			else
			{
				opnum.push_back(ndlist[ch-'A']);
			}
		}
		if (!is_error)
		{
			cout << ans << endl;
		}
	}
#endif
}



猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80991547
今日推荐