Resolução de problemas/Matrix chain multiplication

Origem: Wikilivros, livros abertos por um mundo aberto.

Tratamento de Expressões[editar | editar código-fonte]

O problema 442 (Matrix Chain Multiplication) é um simples tratamento de multiplicação de matrizes obedecendo a uma gramática dada no problema.

A implementação abaixo é uma sugestão de implementação:

 /*Estrutura para armazenar a entrada com as matrizes*/
 typedef struct matrix_{<br>
 	int m;
 	int n;
 } matrix;
 bool erro;
 matrix m[27];
 /*Número de casos de teste*/
 int t;
 int nexp;
 /*Templates pra fazer o processamento das expressões*/
 list<matrix> l;
 stack<matrix> s;
 /*Função  principal que faz a leitura e impressão do resultado ótimo para a multiplicacao*/
 /*de matrizes dadas como entrada*/
 int main(){
 	char nm;
 	int valor;
 	cin>>t;
 	while(t>0){
 		cin>>nm;
 		cin>>m[nm-'A'].m>>m[nm-'A'].n;
 		//cout<<nm<<" "<<m[nm-'A'].m<<m[nm-'A'].n<<"\n";
 		t--;
 	}
 	getchar();
 	while(1){
 		nexp = 0;
 		erro = false;
 		valor = expcalc();
 		if(valor == -3)
 			break;
 		else if(erro){
 			cout<<"error\n";
 			while(!s.empty()) s.pop();
 			l.clear();
 		}else{
 			cout << valor << "\n";
 		}
 	}
 	return 0;
 } 
 /* Função responsável pela leitura e armazenamento na lista l da expressão*/
 /* Esta função recursiva vai fazer operações de inserção e retirada de matrizes entre/*
 /* a lista e a pilha de tal forma que as matrizes aninhadas mais internas tenham maior*/
 /* precedência em relação as mais externas*/
 int expcalc(){
 	char c;
 	matrix a;
 	int valor;
 	c = getchar();
  	if(c == '\n' && erro)
 		return -1;
 	/*Ao encontrar um (, Algarismo alfanumérico, os valores são inseridos na lista*/
 	if(c == EOF)
 		return -3;
  	if(c == '('){
 		//cout<<"(\n";
 		a.m = -2;
 		a.n = -2;
 		l.push_back(a);
 		return expcalc();
 	/*Ao encontrar um ), os valores sao retirados da lista e inseridos na pilha*/
        /*até encontrar um ( ou a lista ficar vazia*/
 	/*Após é chamada a função para calcular o valor ótimo da subexpressão na pilha*/
 	/*Os valores ótimos das subexpressões são somados e retornados pela função expcalc */ 
 	}else if(c == ')'){
 		//cout<<")\n";
 		a = l.back();
 		while(a.m != -2 && a.n != -2){
 			s.push(a);
 			l.pop_back();
 			a = l.back();
 		}
 		l.pop_back();
 		valor = des1();
 		if(valor == -1)
 			return expcalc();
 		l.push_back(s.top());
 		s.pop();
 		//cout<<valor<<"\n";
 		return valor + expcalc();
 	}else if(c >= 'A' && c <= 'Z'){
 		nexp++;
 		l.push_back(m[c-'A']);
 		//cout<<c<<"\n";
 		return expcalc();
 	}
 	if(nexp == 1){
 		l.pop_front();
 		return 0;
 	}else{
 		valor = des();
 		if(erro)
 			return -1;
 		return valor;
 	}
 	
 } 
 /*des e des1 implementão as funções que multiplicão as subexpressões de entrada, a */
 /*diferença está que des1 utiliza os valores armazenados na pilha enquanto que des os da */
 /*lista*/<br>
 int des1(){
 	matrix a, b, c;
 	int valor;
 	a = s.top();
 	s.pop();
 	if(s.empty()){
 		s.push(a);
 		return 0;
 	}
  	b = s.top();
 	s.pop();
  	if(s.empty()){
 		/*cout<<"OK 1\n";
 		cout<<a.m<<" "<<a.n<<" "<<b.m<<" "<<b.n  <<"\n";*/
 		if(a.n != b.m){
 			erro = true;
 			return -1;
 		}
 		c.m = a.m;
 		c.n = b.n;
 		s.push(c);
 		return a.m*a.n*b.n;
 	}else{
 		if(a.n != b.m){
 			erro = true;
 			return -1;
 		}
 		c.m = a.m;
 		c.n = b.n;
 		s.push(c);
 		valor = a.m*a.n*b.n;
 		return valor + des1();
 	}
  } 
 
 int des(){
 	matrix a, b, c;
 	int valor;
  	a = l.front();
 	l.pop_front();
  	if(l.empty())
 		return 0;
 	b = l.front();
 	l.pop_front();
 	if(l.empty()){
 		/*cout<<"OK\n";*/
 		//cout<<a.m<<" "<<a.n<<" "<<b.m<<" "<< b.n <<"\n";
 		if(a.n != b.m){
 			erro = true;
 			return -1;
 		}
 		return a.m*a.n*b.n;
 	}else{
 		if(a.n != b.m){
 			erro = true;
 			return -1;
 		}
 		c.m = a.m;
 		c.n = b.n;
 		l.push_front(c);
 		valor = a.m*a.n*b.n;
 		return valor + des();
 	}
 }

Veja esse problema em: [1]