欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

csp 201912-3 化学方程式

程序员文章站 2022-05-12 14:54:38
...

csp 201912-3	化学方程式
csp 201912-3	化学方程式
csp 201912-3	化学方程式
解答:(40分未考虑)系数可以是多位数,(70分未考虑)括号嵌套可以是:((化学式))(化学式)。思路按照巴克斯范式分析。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct big{
	int count;
	int small[26];
};// 比如:big['C'-'A'].small['a'-'a'] = 9,表示Ca元素系数9;big['C'-'A'].count = 9,表示C元素系数9; 

typedef struct big big;

void dealEqualSign(char* equation,big* left,big* right);// 处理'='号,得到两个表达式 
void dealPlusSign(char* expr,int which,big* left,big* right);// 处理'+'号,得到每个部分 
void dealPart(char* part,int which,big* left,big* right);// 处理部分,得到ceof
void dealBracket(char* formula,int ceof,int which,big* left,big* right);// 处理括号,得到化学式 
void dealTerm(char* moele,int ceof,int which,big* left,big* right);// 处理化学式,得到元素 
void dealElement(char* term,int size,int ceof,int which,big* left,big* right);// 处理元素 
int judgeLR(big* left,big* right);// 判断是否相等 

int main(){
	int n,i,j,k;
	scanf("%d",&n);
	for(i=0; i<n; i++){
		big left[26],right[26];
		for(j=0; j<26; j++){
			left[j].count = right[j].count = 0;
			for(k=0; k<26; k++){
				left[j].small[k] = right[j].small[k] = 0;
			}
		}
		char equation[1001]={'\0'};
		scanf("%s",equation);
		dealEqualSign(equation,left,right);
		if(judgeLR(left,right) == 1){
			printf("Y\n");
		}else{
			printf("N\n");
		}
	}
	return 0;
}

// 处理'='号,得到两个表达式 
void dealEqualSign(char* equation,big* left,big* right){
	if(equation[0]=='\0') return;
	int i=-1;
	while(equation[++i] != '=');
	equation[i] = '\0';
	dealPlusSign(equation,0,left,right);
	dealPlusSign(equation+i+1,1,left,right);
}

// 处理'+'号,得到每个部分 
void dealPlusSign(char* expr,int which,big* left,big* right){
	if(expr[0]=='\0') return;
	
	int i=0;
	while(expr[i] != '\0' && expr[i] != '+'){
		i++;
	};
	if(expr[i] == '+'){
		expr[i]='\0';
		dealPart(expr,which,left,right);
		dealPlusSign(expr+i+1,which,left,right);
	}else{
		dealPart(expr,which,left,right);
	}
}

// 处理部分,得到ceof
void dealPart(char* part,int which,big* left,big* right){
	if(part[0]=='\0') return;
	int ceof = 0, i=0;
	while('0'<=part[i] && part[i]<='9'){
		ceof = ceof*10+(part[i]-'0');
		i++;
	}
	if(ceof == 0) ceof = 1; 
	dealBracket(part+i,ceof,which,left,right);
} 

// 处理括号,得到化学式 
void dealBracket(char* formula,int ceof,int which,big* left,big* right){
	if(formula[0] == '\0') return;
	int i,lk=-1,rk=-1,rk_t=0,lk_t=0,fsize=strlen(formula);
	for(i=0; i<fsize; i++){
		if(formula[i] == '('){
			if(lk == -1)
				lk=i; // 只要第一个出现的左括号 
			lk_t++;
		}
		if(formula[i] == ')'){
			rk=i; // 要最后一个出现的右括号 
			rk_t++;
		}
		if(lk_t != 0 && lk_t == rk_t) break;
	}
	if(lk != -1){
		formula[lk]='\0';
		dealTerm(formula,ceof,which,left,right);
		
		formula[rk]='\0';
		int ceof2 = 0;
		i = rk+1;
		while('0' <= formula[i] && formula[i] <= '9'){
			ceof2 = ceof2*10+(formula[i]-'0');
			i++;
		}
		if(ceof2 == 0) ceof2 = ceof;
		else ceof2 *= ceof;
		dealBracket(formula+lk+1,ceof2,which,left,right);
		
		dealBracket(formula+i,ceof,which,left,right);

	}else{
		dealTerm(formula,ceof,which,left,right);
	}
}

// 处理化学式,得到元素 
void dealTerm(char* moele,int ceof,int which,big* left,big* right){
	if(moele[0] == '\0') return;
	int msize = strlen(moele);
	int ceof2 = 0,i=1,start=0;
	if(moele[i] >= 'a' && moele[i] <= 'z'){// 元素为大小写字母 
		++i;
		while('0'<=moele[i] && moele[i]<='9'){
			ceof2 = ceof2*10+(moele[i]-'0');
			i++;
		}
		if(ceof2 == 0){ 
			ceof2 = ceof;
		}else{
			ceof2 *= ceof;
		} 
		dealElement(moele,2,ceof2,which,left,right);
		dealTerm(moele+i,ceof,which,left,right);
	}else{
		while('0'<=moele[i] && moele[i]<='9'){
			ceof2 = ceof2*10+(moele[i]-'0');
			i++;
		}
		if(ceof2 == 0){ 
			ceof2 = ceof;	
		}else{
			ceof2 *= ceof;
		}
		dealElement(moele,1,ceof2,which,left,right);
		dealTerm(moele+i,ceof,which,left,right);
	}
}

// 处理元素 
void dealElement(char* term,int size,int ceof,int which,big* left,big* right){
	if(term[0]=='\0') return;
	if(size == 1){
		if(which == 0){
			left[(int)(term[0]-'A')].count += ceof;
		}else{
			right[(int)(term[0]-'A')].count += ceof;
		}
	}else{
		if(which == 0){
			left[(int)(term[0]-'A')].small[(int)(term[1]-'a')] += ceof;
		}else{
			right[(int)(term[0]-'A')].small[(int)(term[1]-'a')] += ceof;
		}
	}
}

// 判断是否相等 
int judgeLR(big* left,big* right){
	int flag = 1,i,j;
	for(i=0; i<26; i++){
		if(left[i].count != right[i].count){
			flag = 0;
			break;
		}
		for(j=0; j<26; j++){
			if(left[i].small[j] != right[i].small[j]){
				flag = 0;
				i = 26;
				break;
			}
		}
	}
	return flag;
}