这是去年12月参加CCF没能做完的一道题,当时只获得了60分。今天闲来无事把之前的代码完善了一下,在练习平台上中终于100分通过。(第一次发博客,发一道水题试试水)

题目描述



解题思路

这道题难度不大,题目描述也清晰易懂,关键在于分析清方程式的结构。我把方程式做如下分解
方程式: <表达式> < = > <表达式>
表达式:<项> < + 项>*
项:{<系数>| 空串 } <化学式>
化学式:<(化学式)>* <元素> {<角标>| 空串 }* | <(化学式)>*
元素: <大写字母><小写字母> | <大写字母>
系数、角标:<非零数字><数字>*
(星号表示有0或N个相同的结构连接在一起)

通过分析可以发现每个方程式都被等号分为左右两个表达式,只要确保等号两边表达式中元素种类和每种元素的原子数量相同即可。表达式又被加号分为多个项。不难看出每个项的结尾只能是加号、等号或者方程式末尾,我选择根据这三个分界点找出每一项,然后逐一处理。

项由系数和化学式组成,系数只会在项的开头出现,所以只需在项的开头找出数字串并记录,得到项的系数,如果没有前缀数字串则记系数为1。接下来化学式的处理是最麻烦的,因为括号的嵌套可能会在化学式中出现。所以化学式中会混杂着元素和括号,并且元素和由括号包括的基团都可以带有后缀角标。括号表达式需要向上层括号传递数据,我这里使用一种笨办法,比较费时间空间。对每一层括号都调用一次函数,遇到左括号就调用本身。当扫描到右括号时,说明这层括号表达式处理完毕,随后将数据返回给上层括号函数。抛开括号,对元素的处理则十分容易,仅仅是判断大小写字母还是数字的问题而已。

下面是我实现的代码,在测试平台100分通过,但不确定有没有特别的用例会出问题,希望大家给出指点。

代码

#include<bits/stdc++.h>
using namespace std;
int n;
string equa;
int getelem(int i, map<string,int>& element_upper, set<string>& eles, int time){string ele="";if(equa[i]>='A' && equa[i]<='Z'&& i<equa.length()){ele+=equa[i];i++;if(equa[i]>='a' && equa[i]<='z'&& i<equa.length()){ele+=equa[i];i++;}}int num=0;while(equa[i]>='0' && equa[i]<='9'&& i<equa.length()){num=num*10+equa[i]-'0';i++;}if(num==0) num=1;//计算元素角标,默认为1 if(!element_upper.count(ele)) element_upper[ele]=0;element_upper[ele]+=time*num;//计算表达式对应元素原子数 //cout<< time << ele;eles.insert(ele);//元素表中加入元素 return i;
}
int bracket(int i, map<string,int>& element_upper, set<string>& eles, int time){map<string,int> element;while(equa[i]!=')' && equa[i]!='+' && equa[i]!='='&& i<equa.length()){if(equa[i]=='('){i = bracket(i+1, element, eles, time);}else i=getelem(i,element,eles,time);}int num=0;if(equa[i]==')'){i++;}while(equa[i]>='0' && equa[i]<='9'&& i<equa.length()){num=num*10+equa[i]-'0';i++;}if(num==0) num=1;for(map<string,int>::iterator it=element.begin(); it!=element.end();it++){if(!element_upper.count(it->first)){element_upper[it->first]=0;}element_upper[it->first]+=num*it->second;}return i;
}
void judge(){map<string,int> element_left;map<string,int> element_right;set<string> eles;cin>>equa;int i=0;for(i=0;i<equa.length();i++){int time=0;while(equa[i]>='0' && equa[i]<='9'){time=time*10+equa[i]-'0';i++;}if(time==0) time=1;//计算化学式系数,默认为1 while(equa[i]!='+' && equa[i]!='='){ i=bracket(i,element_left,eles,time);}if(equa[i]=='='){i++;break;}}for(;i<equa.length();i++){int time=0;while(equa[i]>='0' && equa[i]<='9'){time=time*10+equa[i]-'0';i++;}if(time==0) time=1;while(equa[i]!='+' && equa[i]!='=' && i<equa.length()){   i=bracket(i,element_right,eles,time);}}for(set<string>::iterator it=eles.begin();it!=eles.end();it++){if(element_left[*it]!=element_right[*it]){cout<<"N"<<endl;return;}}cout<<"Y"<<endl;
}
int main(){cin>>n;while(n--){judge();}return 0;
}

201912-3 化学方程式 的一种解法相关推荐

  1. usaco Ordered Fractions 顺序的分数(两种解法)

    这题很好玩,这里有两种解法. 第一种我自己写的,先找到所有的既约真分数,然后写了一个cmp函数进行排序最后输出.我写的时候还在想这章不是搜索吗这跟搜索关系不大吧,难道是怕我们思维定式化故意出的题不是搜 ...

  2. 青蛙跳台阶c语言递归函数,青蛙跳台阶问题的四种解法

    http://raychase.iteye.com/blog/1337359 题目:一只青蛙一次可以跳1级台阶,也可以跳2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 这道题还被ITEye放在了博 ...

  3. opengl正方形绕点旋转_一题十五种解法够不够? 旋转,构造,四点共圆乐不停...

    平移,旋转,轴对称是我们初中学习的"几何三大变换".在我们初中阶段学习的几何知识中占据着核心的地位,特别是旋转,那更是核心中的核心(河南中考22题年年考). 如何更好的理解旋转,如 ...

  4. 约瑟夫环问题的两种解法(详解)

    约瑟夫环问题的两种解法(详解) 题目: Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓.于是决定了自杀方式,41个人排成一个圆 ...

  5. 牛客--追债之旅 两种解法

    文章目录 第一种 第二种: 一共两种解法,所以即便你不会最短路,也可以做,甚至爆搜+剪枝的时间和空间消耗小于最短路做法. 第一种 题意: 小明现在要追讨一笔债务,已知有n座城市,每个城市都有编号,城市 ...

  6. java binarytreenode_LeetCode算法题-Binary Tree Paths(Java实现-3种解法)

    这是悦乐书的第199次更新,第206篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第62题(顺位题号是257).给定二叉树,返回所有根到叶路径.例如: 输入: 1 / \ ...

  7. 关于leetcode第K个最大元素的几种解法

    对于这一题我使用了最大堆,快速排序,归并排序几种解法来做这一题,速度最快的是归并排序 使用定值的最小堆每次更新数组最后剩下前k个最大元素,而且堆顶就是我们要的第K个元素. 堆排序: import he ...

  8. [简单题]自定义取余(三种解法)C++实现

    题目链接: 点击打开原题链接 题目意思,就是标题意思. 第一种解法:(加法迭代)用加法来模拟这个(17行代码) int mod256WithoutMod(int number) {if (number ...

  9. 推荐系统炼丹笔记:Embedding在内存问题上的一种解法

    作 者:一元 公众号:炼丹笔记 很多朋友都会发现,修改embedding的大小能对深度模型带来非常大的影响,往往越大的embedding能带来更佳的效果,但是却因为Embedding内存的问题,没法直 ...

  10. jsp判断字符串相等_最长回文字符串三种解法

    先解释一下什么是回文字符串,比如说字符串"aba",无论是从先往后读取还是从后往前读取,结果都是一样的.当给定很长的字符串时,如何快速获取到最长的回文字符串,这也是大厂比较常见的算 ...

最新文章

  1. XHTML标准下的100%高度问题
  2. 网工路由基础(6)BGP协议
  3. 2009年3月全国计算机等级考试二级vfp笔试,2009年3月全国计算机等级考试二级VFP笔试试题及答案.doc...
  4. 【图像超分辨率】Learning Texture Transformer Network for Image Super-Resolution
  5. 手把手教学系列——疯狂Spring Cloud教学视频
  6. 谷歌浏览器外贸版_做外贸没有单怎么办?找客户 供应商的小技巧-跨境电商
  7. Android挂断、接听电话
  8. java君临天下单机游戏_君临天下java单机游戏
  9. 数字电路基础知识——时序逻辑电路之存储器(SRAM、DRAM、ROM)
  10. 信度spss怎么做_怎么用spss处理信度和效度?
  11. LUP分解法求解线性方程组
  12. 珠心算测验 C语言基础
  13. 任正非:管理上的灰色,是我们的生命之树
  14. Linux内核版本说明
  15. 计算机基础表格模拟题,4月全国网络统考资料《计算机应用基础》模拟题及参考答案——电子表格...
  16. 目前流行的Bug缺陷管理工具
  17. JSP大学实用教程(第2版)代码一
  18. RGB YUV的来历及相互转换
  19. 记录一个网易云IM和直播功能中,服务器API的Java调用代码
  20. Logback configuration error detected的终极解决方案

热门文章

  1. python中的时间和时区详解(datetime / dateutil / pytz)
  2. 推荐好轮子【Echarts数据可视化】图表插件 兼容ie6、7、8
  3. UE4蓝图 绑定输入
  4. 【千律】OpenCV基础:图像边缘检测 -- Laplacian 算子和 LoG 算子
  5. 集成运放的电压跟随器有什么作用?
  6. 51单片机外围模块——红外通信
  7. PS下载Adobe Photoshop 2020中文安装教程 亲测可用
  8. 计算机电源维护维修方法,电脑电源维修方法
  9. linux在线汇编编译器,Linux 汇编 Hello World
  10. Java笔记——关于设置自定义字体、全局字体方面和getFont()的使用