CCF 大模拟之化学方程式 201912-3

1 篇文章 0 订阅

题目

给出化学方程式,判断是否配平,所有方程式符合规范
例如:
H2+O2=H2O
2H2+O2=2H2O

解题思路

首先要清楚系数出现位置的三种情况:
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分别记录左右两边的元素个数,再进行比较。
————————————————-
版权声明:本文为CSDN博主「wingrez」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wingrez/article/details/103551680

#include<bits/stdc++.h>
using namespace std;
struct elem{//用结构体存储每个元素的信息
    string name;//元素名字
    int total;//元素数量
    elem(string name,int total):name(name),total(total){}
};
int todigit(string equat,int &i){
    int dig=0;
    while(isdigit(equat[i])>0){
        dig=dig*10+(equat[i]-'0');
        i++;
    }
    return dig;
}
void calcuelem(string equat,map<string,int> &m){
    int len=equat.length();
    int atfirst=1;
    int i=0;
    if(isdigit(equat[i])){//1.整个化学式首部
        atfirst=todigit(equat,i);
    }
    vector<elem> vec_elem;//容器存每一种遇到的元素或者‘( ’   ‘ )’
    for(;i<len;i++){
        if(isdigit(equat[i])){
            int mul=todigit(equat,i);//遇到数字,先把数字算出来
            if(vec_elem[vec_elem.size()-1].name[0]==')'){//2.括号后面
                for(int j=vec_elem.size()-1;j>=0;j--){
                    if(vec_elem[j].name[0]=='('){
                        vec_elem[j].name="*";//标记处理
                        break;
                    }
                    if(vec_elem[j].name[0]==')') vec_elem[j].name="*";
                    else{
                        vec_elem[j].total*=mul;
                    }
                }
            }
            else{//3.元素后面
                vec_elem[vec_elem.size()-1].total*=mul;
            }
            i--;//todigit()处理到数字的下一位
        }
        else if(equat[i]=='('||equat[i]==')'){
            if(equat[i]=='(')   vec_elem.push_back(elem("(",1));
            else vec_elem.push_back(elem(")",1));
        }
        else if(isupper(equat[i])){
            string name="";
            name+=equat[i];
            if(i+1<len&&islower(equat[i+1])){
                name+=equat[i+1];
            }
            vec_elem.push_back(elem(name,1));
        }
    }
    for(int i=0;i<vec_elem.size();i++){
    	if(vec_elem[i].name[0]!='*')
        	m[vec_elem[i].name]+=vec_elem[i].total*atfirst;
    }

}

bool compare(map<string,int> m1,map<string,int> m2){
    if(m1.size()!=m2.size())    return false;
    else{
        map<string,int>::iterator iter1=m1.begin();
        map<string,int>::iterator iter2=m2.begin();
        for(;iter1!=m1.end(),iter2!=m2.end();iter1++,iter2++){
//            cout<<iter1->first<<":"<<iter1->second<< " "<<iter2->first<<":"<<iter2->second<<endl;
            if(iter1->first!=iter2->first||iter1->second!=iter2->second){
                return false;
            }
        }
    }
    return true;
}
int main(){
    int n;
    cin>>n;
    while(n--){
        string equation;
        cin>>equation;//输入化学方程式
        string str="";
        int flag=0;
        map<string,int> map1,map2;
        for(int i=0;i<equation.length();i++){
            if(equation[i]=='+'){//方程式=左右两端分别处理到不同的map中,每一个+分割的计算一次
               if(flag==0) calcuelem(str,map1);
               else calcuelem(str,map2);
               str="";
            }
            else if(equation[i]=='='){
                calcuelem(str,map1);
                str="";
                flag=1;
            }
            else str+=equation[i];
        }
        calcuelem(str,map2);
        bool res=compare(map1,map2);
        if(res==1){
            cout<<"true"<<endl;
        }
        else cout<<"false"<<endl;
    }
}

结果

11
H2+O2=H2O
false
2H2+O2=2H2O
true
H2+Cl2=2NaCl
false
H2+Cl2=2HCl
true
CH4+2O2=CO2+2H2O
true
CaCl2+2AgNO3=Ca(NO3)2+2AgCl
true
3Ba(OH)2+2H3PO4=6H2O+Ba3(PO4)2
true
3Ba(OH)2+2H3PO4=Ba3(PO4)2+6H2O
true
4Zn+10HNO3=4Zn(NO3)2+NH4NO3+3H2O
true
4Au+8NaCN+2H2O+O2=4Na(Au(CN)2)+4NaOH
false
Cu+As=Cs+Au
false

未严格按照原题输入输出编写代码,如有不足多多包涵

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值