2019-12-3化学方程式(还存在一点问题,只有80分)

/*
4Au+8NaCN+2H2O+O2=4Na(Au(CN)2)+4NaOH 这个样例还存在问题

思想:=左边的表达式为正,=右边的为负 ,看map中的键是否为0即可判断是否配平
	括号匹配最简单的方法:遇到左括号变量初始为1,遇到左括号+1,右括号-1,为0即匹配 

*/ 


#include <iostream>
#include <string>
#include <cstring>
#include <map>
using namespace std;
void chai_jia(int start, int end, int p); //将表达式按+左右拆开 
void huaxueshi(int start, int end, int p); //化学式处理 
int get_xishu(int start, int end);
void input (int start, int end, int n);

string str;
map<string, int> ch; 

int main(){
	int n;
	scanf("%d", &n);
	while (n--){
		ch.clear(); //每一轮循环开始之前都要先clear !!! 
		cin >> str;
		if (str.find('=') != string::npos){ //将化学方程式按照=左右拆开分开处理 
			chai_jia(0, str.find('=') - 1, 1); //=左边的为正!! 
			chai_jia(str.find('=') + 1,str.length() - 1, -1); //=右边的为负 !!
		}
		int flag = 1;
		for (map<string, int>::iterator it = ch.begin(); it != ch.end(); it++){
			if (it -> second != 0) { //如果存在键不等于0 ,则没有配平 
				flag = 0; break;
			}
		}
//		for (map<string, int>::iterator it = ch.begin(); it != ch.end(); it++){
//			cout << it -> first << it -> second << endl;
//		}
		if (flag) printf("%c\n", 'Y'); 
		else printf("%c\n", 'N');	
	}


	return 0;
}
void chai_jia(int start, int end, int p){  //这里的逻辑我开始没想出来!!!
	int j; 
	for (int i = start; i <= end; i = j + 1){
		j = str.find('+', i);
		if (j == string::npos || j > end){
			j = end + 1;
		}
		huaxueshi(i, j - 1, p);
	}
}
void huaxueshi(int start, int end, int p){  //求单个部分的元素个数,如 3Ba(OH)4  这个函数是难点!!! 
	int total = get_xishu(start, str.length() - 1) * p; //总系数 
	for (int i = start, j = i + 1; i <= end; i = j, j++){   //i为新开始的第一个,j为开始的第二个,for里面的是难点!!! 
		//数字的话这个函数不会处理 !!
		if (isupper(str[i])){
			if (islower(str[j])&& j <= end){ //注意j的范围约束,j需要<=end  !! 
				j++; //j指向后面的第一个元素 !!
			}
			input(i, j - 1, total * get_xishu(j, str.length() - 1));
		}
		if (str[i] == '('){  
			int flag = 1;
			int k = i + 1;
			while (k <= end){
				if (flag == 0) {
					cout << k << endl;
					j = k; break;
				}
				if (str[k] == ')') flag--;
				if (str[k] == '(') flag++;
				k++;
			}
			huaxueshi(i + 1, k - 2, total * get_xishu(j, str.length() - 1));  //i+1  k-2  j	 
		}
	}
	
}
int get_xishu(int start, int end){
	int count = 0;
	int i = start;
	while ('0' <= str[i] && str[i] <= '9' && i <= end){
		count = count * 10 + str[i] -'0';
		i++;
	}
	return count == 0 ? 1 : count; //注意:count为0时应该返回1,而不是返回count !!!!
}
void input (int start, int end, int n){
	ch[str.substr(start, end - start + 1)] += n;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值