ccf 201912-3 化学方程式(模拟)

4 篇文章 0 订阅

思路: 具体来说没啥坑点,就是嵌套括号的情况需要用一个栈把系数存起来,整体的计算也是用栈把元素分开然后计算,这种题就得把思路捋清楚最好多封装点函数,不然容易乱。


对了,必须要吐槽一下,2019年这几个题的样例都是图片没办法复制,这么长的样例我手敲的,吐血!样例我放在代码最后的注释了,需要可以自取~


代码:

#include <cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
using namespace std;
#define fi first
#define se second
typedef pair<string,int> pa;
const int N = 1005;
string getformula(string &s,int &i)  //提取每个化学式
{
    string ss;
    for(;s[i]!='+' && i<s.size();i++)
        ss+=s[i];
    i++;
    return ss;
}
int getcoef(string s,int &i)  //获得字符串s开始的系数,若没有系数返回1
{
    int ans=0;
    while(isdigit(s[i])&&i<s.size())
        ans=ans*10+s[i]-'0',i++;
    if(ans==0) ans=1;
    return ans;
}
map<string,int> getmap(string s)  //用map获得每个元素的个数
{
    int num=0;
    map<string,int> mp;
    while(num<s.size())
    {
        string ss=getformula(s,num);  //ss表示当前化学式
        int i=0,coef=getcoef(ss,i);    //coef为化学式前面的整体的系数
        stack<pa> item;  //存储化学式中的每一个项及其系数
        bool flag=0;
        while(i<ss.size())
        {

            pa element;
            element.fi+=ss[i++]; //获取完系数的第一个一定是大写字母
            if(i<ss.size() && islower(ss[i]))//如果后面一个为小写字母,与前面是同一个项
                element.fi+=ss[i++];
            element.se=getcoef(ss,i); //获取该项对应的系数
            item.push(element);
        }
        stack<int> digit;  //存储括号外面的系数
        while(item.size())
        {
            pa tem=item.top();
            item.pop();
            if(tem.fi==")") //用栈相当于从右往左计算,遇到)说明左边的括号的元素个数需要乘以括号外的系数
                coef*=tem.se,digit.push(tem.se);
            else if(tem.fi=="(")  //(左边的不需要乘以该括号外面的系数了
                coef/=digit.top(),digit.pop();
            else
                mp[tem.fi]+=coef*tem.se;
        }
    }
    return mp;
}
bool check(string s)
{
    string s1;
    int i;
    for(i=0;s[i]!='=';i++)
        s1+=s[i];
    string s2=s.substr(i+1);
    map<string,int> mp1=getmap(s1),mp2=getmap(s2),mp;
    if(mp1.size()!=mp2.size())
        return false;
    map<string,int>::iterator it;
    for(it=mp1.begin();it!=mp1.end();it++)
    {
        string a=it->first;
        int b=it->second;
        if(mp2.find(a)==mp2.end() || mp2[a]!=b)
            return false;
    }
    return true;
}
int main()
{
    int n;
    string s;
    cin>>n;
    while(n--)
    {
        cin>>s;
        if(check(s))
            cout<<"Y"<<endl;
        else
            cout<<"N"<<endl;
    }
    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
*/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值