442. Умножение матриц
Для того чтобы перемножить
две матрицы с размерами m * n и n
* p, требуется выполнить m * n
* p умножений. В задаче необходимо
вычислить количество операций умножения для заданной последовательности
перемножения матриц.
Вход. Первая строка содержит количество перемножаемых
матриц n (1 £ n £ 26). Каждая из следующих n строк содержит имя матрицы (заглавная латинская буква) и ее
размеры. Следующая часть входных данных содержит матричные выражения, описываемые
грамматикой:
SecondPart
= Line { Line } <EOF>
Line = Expression <CR>
Expression
= Matrix | "(" Expression Expression ")"
Matrix = "A" | "B" |
"C" | ... | "X" | "Y" | "Z"
Выход. Для
каждого входного выражения вывести количество умножений, необходимых для его
вычисления.
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))
0
0
0
error
10000
error
3500
15000
40500
47500
15125
синтаксический анализ
Следует реализовать
синтаксический разбор и интерпретацию строки, содержащую матричное
выражение.
Переменная Error будет установлена в 1, если входное
выражение или синтаксически неверно, или содержит в своем вычислении
произведение несовместимых матриц. Две матрицы a * b и c * d несовместимы
по умножению, если b ¹ c. Массив символов s содержит строку с матричным выражением. Элементы dim[i][0] и dim[i][1] содержат размеры матрицы с именем ‘A’ + i.
Стек st используется при интерпретации входного выражения и
содержит размеры матриц как пары чисел.
int Error, dim[26][2];
char s[1000];
stack<pair<int,int> > st;
В процедурах expression и matrix реализуется
интерпретация входного выражения. В процедуре matrix заносятся в стек размеры
текущей распознаваемой матрицы.
void matrix(void)
{
st.push(make_pair(dim[s[ptr] - 'A'][0],dim[s[ptr]
- 'A'][1]));
ptr++;
}
Процедура expression реализует правило
Expression
= Matrix | "(" Expression Expression ")"
Если распозначаемый символ является открывающей
скобкой, то реализуется вторая часть правила. Иначе символ считается именем
матрицы и вызывается процедура matrix. Если значение Error равно 1, то следует завершить работу процедуры.
void expression(void)
{
pair<int,int> a,b;
if (Error) return;
if (s[ptr] == '(')
{
ptr++;
expression(); if (Error) return;
expression(); if
(Error) return;
После второго вызова процедуры expression на вершине
стека располагаются размеры двух матриц, которые перемножаются. Заносим их в
переменные a и b. Для перемножения матриц
с размерами (a.first, a.second) и (b.first, b.second) следует выполнить a.first * a.second * b.second
операций умножений, в результате получается матрица с размерами (a.first,
b.second).
b =
st.top();st.pop();
a =
st.top();st.pop();
if (a.second != b.first) {Error = 1; return;}
res += a.first *
a.second * b.second;
st.push(make_pair(a.first,b.second));
После распознания двух выражений должна следовать
закрывающаяся скобка. Если ее нет, то установить Error = 1.
if (s[ptr] != ')')
{Error = 1; return;}
ptr++;
} else matrix();
}
Основная часть программы. Читаем количество матриц n и их имена и размеры. Заносим размеры
матриц в массив dim.
scanf("%d\n",&n);
for(i = 0; i < n; i++)
{
scanf("%c %d %d\n",&name,&x,&y);
dim[name - 'A'][0] = x; dim[name - 'A'][1]
= y;
}
Входные выражения читаем в массив s. Вызываем процедуру интерпретации expression. Переменная ptr является
указателем на текущий символ в строке s.
while(gets(s))
{
Error = res = ptr = 0;expression();
Чистим содержание стека st для его использования при интерпретации следующего выражения.
while(!st.empty())
st.pop();
В зависимости от значения переменной Error выводим результат. Переменная res содержит
количество выполненых умножений.
if (Error) printf("error\n");
else printf("%d\n",res);
}