化学方程式

来源:CCF

标签:

参考资料:

相似题目:

题目

化学方程式,也称为化学反应方程式,是用化学式表示化学反应的式子。给出一组化学方程式,请你编写程序判断每个方程式是否配平(也就是方程式中等号左右两边的元素种类和对应的原子个数是否相同)。
本题给出的化学方程式由大小写字母、数字和符号(包括等号=、加号+、左圆括号和右圆括号)组成,不会出现其他字符(包括空白字符,如空格、制表符等),化学方程式的格式与化学课本中的形式基本相同(化学式中表示元素原子个数的下标用正常文本,如H2O写成H2O),用自然语言描述如下:

  • 化学方程式由左右两个表达式组成,中间用一个等号三连接,如2H2+O2=2H2O;
  • 表达式由若干部分组成,每部分由系数和化学式构成,部分之间用加号+连接,如2H2+O2、2H2O;
  • 系数是整数或空串,如为空串表示系数为1;
  • 整数由一个或多个数字构成;
  • 化学式由若干部分组成,每部分由项和系数构成,部分之间直接连接,如H2O、CO2、Ca(OH)2、Ba3(PO4)2;
  • 项是元素或用左右圆括号括起来的化学式,如H、Ca、(OH)、(P04);
  • 元素可以是一个大写字母,也可以是一个大写字母跟着一个小写字母,如H、O、Ca。

输入

从标准输入读入数据。
输入的第一行包含一个正整数n,表示输入的化学方程式个数。
接下来n行,每行是一个符合定义的化学方程式。

输出

输出到标准输出。
输出共n行,每行是一个大写字母Y或N,回答输入中相应的化学方程式是否配平。

输入样例1

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

输出样例1

N
Y
N
Y
Y
Y
Y
Y
Y
Y
N

提示

1<=n<=100
输入的化学方程式都是符合题目中给出的定义的,且长度不超过1000
系数不会有前导零,也不会有为零的系数化学方程式的任何一边,其中任何一种元素的原子总个数都不超过10^9

解题思路

首先要清楚系数出现位置的三种情况:
1、整个化学式的首部
2、元素的右部
3、右括号的右部

如32Ba((OH)2(CO3)2)3(暂不考虑化学式的合法性)
我们从系数入手,在第一种情况下,该系数作用于化学式中的所有元素;在第二种情况下,该系数作用于紧接着的左边的元素;在第三种情况下,该系数作用于紧接着的左边的匹配括号里的所有元素,请通过上例理解。
为此,我们考虑使用一个数组将化学式的各部分存储起来arr,实现逻辑如下:
1、顺序遍历化学式
2、计算系数的第1种情况,也就是整个化学式的系数factor,继续遍历。
3、遇到左或右括号时,将左或右括号加入到arr中;遇到大写字母时,获取元素名称,将元素名称加入到arr中;遇到数字时,不存到arr中,根据系数的第2、3种情况相应处理(第1种情况已经在第二步处理完成)。
4、对于系数的第2种情况,此时数组arr的最后一个元素就是元素名称,系数作用于它即可;对于系数的第3种情况,从数组尾部逆序遍历,直到遇到左括号,将系数作用于这个范围中的元素,同时要将这一对匹配括号从数组中删除。
至此处理化学式的过程结束。
对于整个化学方程式,将其从等号两边分开处理。使用两个map分别记录左右两边的元素个数,再进行比较。

参考代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<string>
#include<sstream>
#include<map>
#include<vector>
using namespace std;struct Elem{ //元素 string name; //名称 int num; //个数 Elem(string _name, int _num): name(_name), num(_num){}
};int toNumber(string str, int &pos){ //从str的pos位置开始,得到一个数字 int num=0;while(isdigit(str[pos])){num=num*10+str[pos]-'0';pos++;}return num;
} void calc(string &str, map<string, int> &mp){stringstream ss(str);string item;while(getline(ss, item, '+')){ //获取每一个化学式,如 32Ba((OH)2(CO3)2)3 vector<Elem> arr; //存储化学式的分解序列, 如 Ba、(、(、O、H、)、(、C、O、)、) int factor=1; //整个化学式的系数,默认为1 int i=0;if(isdigit(item[i])) factor=toNumber(item,i); //计算化学式系数while(i<item.size()){if(isdigit(item[i])){ //处理数字int num=toNumber(item,i);if(arr[arr.size()-1].name==")"){ //序列最后一个元素是右括号 int j=arr.size()-1;arr[j].name="*"; //将右括号标记为*,忽略它的存在 while(arr[--j].name!="("){arr[j].num*=num;}arr[j].name="*"; //将左括号标记为*,忽略它的存在 }else arr[arr.size()-1].num*=num; //序列最后一个元素是元素名称 }else if(item[i]=='('){ //处理左括号 arr.push_back(Elem("(", 0));  //括号加入到序列中i++;}else if(item[i]==')'){ //处理右括号arr.push_back(Elem(")", 0));  //括号加入到序列中if(i+1==item.size() || !isdigit(item[i+1])) item.insert(i+1,"1"); //考虑到右括号右边可能不出现数字,补充底数1 i++;}else if(isupper(item[i])){ //处理大写字母 //得到元素名称 string name="";name+=item[i]; //大写字目 i++;if(islower(item[i])){ //小写字母 name+=item[i];i++;}arr.push_back(Elem(name,1)); //名称加入到序列中 }}for(int i=0; i!=arr.size(); ++i){ //将“元素->个数”保存到map中 if(arr[i].name=="*") continue; //忽略序列中括号的存在 mp[arr[i].name]+=arr[i].num*factor;}}}bool judge(map<string, int> &left, map<string, int> &right){ //判断两个map是否相同 if(left.size()!=right.size()) return false;for(map<string, int>::iterator it=left.begin(); it!=left.end(); ++it){if(right[it->first]!=it->second) return false;}return true;
}int main(){int n;scanf("%d", &n);for(int i=0; i<n; ++i){map<string, int> left, right;string str, lstr, rstr;cin>>str;stringstream ss(str);getline(ss, lstr,'='); //得到等号左边的字符串 getline(ss, rstr); //得到等号右边的字符串 calc(lstr, left); //计算左字符串 calc(rstr, right);if(judge(left, right)) cout<<"Y"<<endl;else cout<<"N"<<endl; }return 0;
}

CCF计算机软件能力认证试题练习:201912-3 化学方程式相关推荐

  1. CCF计算机软件能力认证试题练习:201903-1 小中大

    小中大 来源:CCF 标签: 参考资料: 相似题目: 背景 在数据分析中,最小值最大值以及中位数是常用的统计信息. 题目 老师给了你 n 个整数组成的测量数据,保证有序(可能为升序或降序),可能存在重 ...

  2. CCF计算机软件能力认证试题练习:201803-2 碰撞的小球

    碰撞的小球 来源:CCF 标签: 参考资料: 相似题目: 题目 数轴上有一条长度为L(L为偶数)的线段,左端点在原点,右端点在坐标L处.有n个不计体积的小球在线段上,开始时所有的小球都处在偶数坐标上, ...

  3. CCF计算机软件能力认证试题练习:201809-2 买菜

    买菜 来源:CCF 标签: 参考资料: 相似题目: 题目 小H和小W来到了一条街上,两人分开买菜,他们买菜的过程可以描述为,去店里买一些菜然后去旁边的一个广场把菜装上车,两人都要买n种菜,所以也都要装 ...

  4. CCF计算机软件能力认证试题练习:201909-2 小明种苹果(续)

    小明种苹果(续) 来源:CCF 标签: 参考资料: 相似题目: 题目 小明在他的果园里种了一些苹果树,这些苹果树排列成一个圆.为了保证苹果的品质,在种植过程中要进行疏果操作.为了更及时地完成疏果操作, ...

  5. CCF计算机软件能力认证试题练习:201609-3 炉石传说

    炉石传说 来源:CCF 标签: 参考资料: 相似题目: 题目 <炉石传说:魔兽英雄传>(Hearthstone: Heroes of Warcraft,简称炉石传说)是暴雪娱乐开发的一款集 ...

  6. CCF计算机软件能力认证试题练习:201803-4 棋局评估

    棋局评估 来源:CCF 标签: 参考资料: 相似题目: 题目 Alice和Bob正在玩井字棋游戏. 井字棋游戏的规则很简单:两人轮流往3*3的棋盘中放棋子,Alice放的是"X", ...

  7. CCF计算机软件能力认证试题练习:201612-2 工资计算

    工资计算 来源: 标签: 参考资料: 相似题目: 题目 小明的公司每个月给小明发工资,而小明拿到的工资为交完个人所得税之后的工资.假设他一个月的税前工资(扣除五险一金后.未扣税前的工资)为S元,则他应 ...

  8. CCF计算机软件能力认证试题练习:201712-3 Crontab

    Crontab 来源: 标签: 参考资料: 相似题目: 题目 输入 输出 输入样例 3 201711170032 201711222352 0 7 * * 1,3-5 get_up 30 23 * * ...

  9. CCF计算机软件能力认证试题练习:201512-2 消除类游戏

    消除类游戏 来源: 标签: 参考资料: 相似题目: 题目 消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行m列的游戏棋盘上进行,棋盘的每一行每一列的方格上放着一个有颜色的棋子,当一行或一列上有 ...

最新文章

  1. tp5 if 如果有html判断,tp5条件判断,in,notin,between,if等
  2. oracle导入dmp文件加条件,oracle 导入DMP文件时IMP-00013: 只有 DBA 才能导入由其他 DBA 导出的文件...
  3. 论文浅尝 | 面向时序知识图谱推理的循环事件网络
  4. 在c语言中数组下标的最小值,数组元素下标的上限_c语言中,数组元素的下标下限为...
  5. 【记录】idea创建springboot多模块项目
  6. 【二分图】【最大匹配】【匈牙利算法】CODEVS 2776 寻找代表元
  7. JS的Document类型
  8. C语言零基础入门级学习程序框架【系统学习第一天】
  9. 在mac 上安装 mpkg
  10. 简单使用ember后的几点感想
  11. Ubuntu 重装显卡驱动(因内核升级导致失效后)
  12. 【图像去噪】基于matlab小波变换图像去噪(MSE和SNR)【含Matlab源码 2192期】
  13. SwiftUI3 新组件教程之 TimelineView 制作一闪一闪星耀效果(中文教程)
  14. 30分钟教你写出10分的淘宝标题
  15. 【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线 离散化+线段树
  16. 戴尔电脑最新bios设置图解介绍
  17. 清华大学计算机考研机试KY6 手机键盘
  18. RL——Policy Gradient类方法
  19. 一键获取前程无忧招聘信息,并存储到excel中,全程只需要输入职位名称(51job 你要的自动化 这里全都有~~~)
  20. 图论(17)平面图概念与性质

热门文章

  1. 复现SCI论文图表:棒棒糖图|渐变|legeng设置
  2. 关于淘宝api的理解与认知
  3. 华为端口隔离实现原理及配置命令
  4. 一份简单的调查问卷数据库设计
  5. Fast R-CNN解读:单阶段,多任务完成检测
  6. PMP第八章重要知识点
  7. EXCEL取消合并单元格并填充每个取消合并后的单元格
  8. 【ISP】Contrast
  9. 整理了一些可以发外链的网站,分享几十个发外链的网站
  10. OGG-00446的解决方法: