CCF 2019-12 第三题 化学方程式配平(100分)

CCF 2019-12 第三题 化学方程式配平(100分)_第1张图片
CCF 2019-12 第三题 化学方程式配平(100分)_第2张图片
CCF 2019-12 第三题 化学方程式配平(100分)_第3张图片
CCF 2019-12 第三题 化学方程式配平(100分)_第4张图片

题解:

字符串模拟
  题目意思很明确就是判断化学方程式是否配平。
基本思路:就是对化学方程式左边和右边的元素进行计数,然后判断所有的元素的数量是否相等即可。
  第一步:对字符串进行拆分
     1、以 ‘=’ 进行拆分,将字符串分为左右两个串
     2、分别将左右两个串以 ‘+’ 进行拆分,得到一个个的化学式
  第二步:提取化学式最外面的倍数,比如3H2O,需要提取3,需要对内部元素都乘以3。
  第三步:dfs单独对一个化学式进行处理,为什么要用dfs?因为化学式会出现括号嵌套的情况,需要dfs对每个括号单独处理。注意需要记录倍数,下一次要将倍数计算好后传入,每一次计数都需要对倍数进行处理。
细节:
  1、元素为一个大写或者一个大写一个小写
  2、多层括号嵌套
  3、括号后面的数字,需要转换为倍数传入
  4、时刻注意防止越界
  5、对空串单独判断

复杂度分析:对一个字符串扫一遍为O(len) ,由于含有括号,需要对字符串进行切割,字符串切割复杂度为O(len),所以每一个字符串处理复杂度为O(len2),map复杂度为O(mlog2(m))小于O(len2),复杂度取大的。n个字符串,总复杂度为O(n(len2))

代码(有注释):

#include
using namespace std;
#define IOS ios::sync_with_stdio(false)
#define ll long long
#define maxn 1005
#define inf 1000000000

//对字符串分割,分隔符为sp
vector split_str(string str,char sp)
{
    vectorV;
    for(int i=0; i=0; k--)
    {
        num1+=(num[k]-=48)*ten;
        ten*=10;
    }
    return num1;
}

/**
    对单个化学式进行计数:
    利用dfs对括号进行拆解,同时记录每次记录倍数
    对于非括号内的,直接计数即可(当然要乘以倍数)
    比如 4AL(Au(CN)2)3  下一次dfs将传入 Au(CN)2 传入倍数3
**/
void dfs(map&m1,string str,int num1)
{
    for(int k=0; k='0'&&str[j]<='9')
                    num.push_back(str[j]);
                else
                    break;
            }
            int num2=1;
            if(num!="")
                num2=get_num(num);
            //cout<<"k="<='a'&&str[k+1]<='z')
            {
                xx.push_back(str[k+1]);
                k++;
            }
            k++;
            string num="";
            while(k='0'&&str[k]<='9')
            {
                num.push_back(str[k]);
                k++;
            }
            int num2=1;
            if(num!="")
                num2=get_num(num);

            m1[xx]+=num2*num1;
        }
    }
}

/**
    1、对化学方程式左边或者右边进行处理
    2、处理化学式初始倍数,如4AL(Au(CN)2)3 初始倍数为最前面的4
    3、分别处理每个化学式 dfs
**/
void get_map(map&m1,vector&V1)
{
    for(int j=0; j='0'&&V1[j][k]<='9')
                num+=V1[j][k];
            else
                break;
        }
        int num1;
        if(num!="")
        {
            reverse(V1[j].begin(),V1[j].end());
            for(int k=0; k&m1,map&m2)
{
    return m1==m2;
}

//打印map
void print_map(map&m1)
{
    for(map::iterator p=m1.begin(); p!=m1.end(); p++)
        {
            cout<<(*p).first<<","<<(*p).second<<"\n";
        }
    cout<<"---------------\n";
}

int main()
{
    IOS;
    ll n;
    cin>>n;

    for(int i=1; i<=n; i++)
    {
        mapm1,m2;

        string str;
        cin>>str;
        vectorV=split_str(str,'=');
        vectorV1=split_str(V[0],'+');
        vectorV2=split_str(V[1],'+');
        get_map(m1,V1);
        get_map(m2,V2);
        /*cout<<"m1:\n";
        print_map(m1);
        cout<<"m2:\n";
        print_map(m2);*/
        if(equal_map(m1,m2))
            cout<<"Y\n";
        else
            cout<<"N\n";
    }
    return 0;
}

后记:此题模了两小时,CCF大模拟题果然名不虚传

你可能感兴趣的:(字符串,dfs,模拟)