201912-3化学方程式

题目描述

CCF认证201912-3. 化学方程式题目描述

C++代码

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
/*
利用unordered_map<string, int> ans存储整个化学方程式中出现的原子及其对应个数。
先按=将整个方程式分成两部分。左部分所有原子默认基本系数为1,右部分所有原子默认基本系数为-1。每部分最终的原子个数要乘上这个基本系数,这样处理完整个方程式中所有原子,如果配平成功所有原子对应个数应该均为0;否则有原子个数不为0 。
对于按=将分成的两部分,再按+分成多个化学式。针对每个化学式统计每种原子出现的个数。那么如何处理带()的化学式呢?我们可以采取递归处理的方法,针对遇到的每个(,找出其对应的)的位置,递归处理该()内的化学式,注意此时该()内的系数要乘上该()后紧邻的数字。找出(对应的)的方法是,设立一个变量num,初始化为1,遍历(之后的所有字符,遇到一个(就让num加1,遇到一个)让num减1,那么使num==0的)字符即为(对应的)。
*/
int n;
string formula;
unordered_map<string, int>ans;
int computeDigit(int first, int last)
{
	int i = 0;
	for (; first <= last&&isdigit(formula[first]); first++)
	{
		i = i * 10 + formula[first] - '0';
	}
	return i == 0 ? 1 : i;
}
void f(int first, int last, int e)//计算formula的[f,l]区间的原子及对应系数 这是一个+分割的
{
	if (first == last || last - first == 1 && islower(formula[last]))
	{
		ans[formula.substr(first, last - first + 1)] += e;
		return;
	}
	//2nacl 先让e * 最前面的数
	e *= computeDigit(first, last);
	for (int i = first, j = i + 1; i <= last; i = j, ++j)//遍历化学式
	{
		if (isupper(formula[i]))//一般原子是2个字符或1个 NaOH
		{
			if (j <= last&&islower(formula[j]))//后面是小写
				++j;
			int k = j;
			f(i, k - 1, e*computeDigit(j, last));//第三个参数思考一下
		}
		else if (formula[i] == '(')
		{
			for (int num = 1; num != 0; ++j)
			{
				if (formula[j] == '(')
					++num;
				else if (formula[j] == ')')
					--num;
			}
			int k = j;
			f(i + 1, k - 1, e*computeDigit(j, last));
		}
	}
}
void expression(int first, int last, int e)//按+分离出所有化学式
{
	for (int i = first,j=first; i <= last; i=j+1)
	{
		j = formula.find('+', i);
		if (j == string::npos || j > last)
			j = last + 1;
		f(i, j - 1, e);//可能没有加号 然后直接找到最后
	}
}
int main()
{
	scanf("%d", &n);
	getchar();
	while (n--)
	{
		getline(cin, formula);
		ans.clear();//必须clear
		int k = formula.find('=');
		expression(0, k - 1, 1);
		expression(k + 1, formula.size() - 1, -1);
		int flag = 1;
		for (unordered_map<string, int> ::iterator it = ans.begin(); it != ans.end(); it++)
		{
			if (it->second != 0)
			{
				flag = 0;
				break;
			}
		}
		if (flag)
			printf("Y\n");
		else
			printf("N\n");
	}
	return 0;
}
/*
11
H2+O2=H2O
2H2+O2=2H2O
H2+Cl2=2NaCl
H2+Cl2=2HCl
CH4+2O2=CO2+2H2O
CaCl2+2AgNO3=Ca(NO3)2+2AgCl
3Ba(OH)2+2H3PO4=6H2O+Ba3(PO4)2
3Ba(OH)2+2H3PO4=Ba3(PO4)2+6H2O
4Zn+10HNO3=4Zn(NO3)2+NH4NO3+3H2O
4Au+8NaCN+2H2O+O2=4Na(Au(CN)2)+4NaOH
Cu+As=Cs+Au
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章