201912-3 化学方程式
程序员文章站
2022-05-12 14:56:50
...
题目描述
解题思路
/*
首先要清楚系数出现位置的三种情况:
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<iostream>
#include<map>
#include<sstream>
#include<string>
#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){//从string pos处得到数字
int num=0;
while(isdigit(str[pos])){//判断字符是否为数字 #include<cstdio>
num=num*10+str[pos]-'0';//针对系数为大于一位的情况设计
pos++;//最后的出结果时pos指向的已经不再是数字了
}
return num;
}
void calc(string &str,map<string,int> &mp){//计算化学式各元素的元素个数
stringstream ss(str);// 整个输入流 将str转化为流信息 用getline()来对输入流分块处理#include<sstream>
string item;// 每一个小块化学式
while(getline(ss,item,'+')) {//获取每一个化学式,如 32Ba((OH)2(CO3)2)3 ss表示一个输入流,item 用来存储输入流中的流信息+ 所设置的截断字符
vector<elem> arr;//存储化学式的分解序列, 如 Ba、(、(、O、H、)、(、C、O、)、)
int factor=1;//系数初始化为一
int i=0;
if(isdigit(item[i]))
factor=toNumber(item,i);
while(i<item.size()){//对每一个小化学式内部处理 此时i=1 只要处理了数字 i自动加一
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(!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中 对mp赋值
{
if(arr[i].name=="*") continue;//忽略序列中括号的存在
mp[arr[i].name]+=arr[i].num*factor;
}
}
}
bool judge(map<string,int> &left,map<string,int> &right)
{
if(left.size()!=right.size())
return false;
map<string,int>::iterator it;//注意迭代器的定义方法
for(it=left.begin();it!=left.end();it++){
if(right[it->first]!=it->second)
return false;
}
return true;
}
int main(){
int n;
cin>>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;
}