CCFCSP认证 2019-12C 化学方程式

题目大意

按题目所给,判断一个方程式是否配平,样例若干

考点

括号匹配

思路

在这里插入图片描述

上图是题目给出的巴科斯范式,一定要结合文字完全看明白。
这个巴科斯范式主要是定义了一个层级关系,
化学方程式 = 表达式 ‘=’ 表达式
表达式 = 式子’+‘式子’+‘…’+‘式子
式子=系数+化学式
系数=不含前导0的十进制数
公式则比较复杂,涉及括号嵌套。

那么该怎么计算化学式中每个元素的出现次数呢?
例如:3A2(B(DC)3)4 (3为化学式的系数)
贡献为3*(2A+4(B+3*(D+C)))
想象一个指针正在正向扫描,每当指针穿过一层左括号,其内部的所有元素的都要在当前系数的基础上再乘以该括号的系数;而每当指针穿过一层右括号,都要在当前系数的基础上除以该括号的系数。
然后发现,这不就是栈吗?穿过左括号时,使用括号匹配找到右括号后面的系数,入栈,同时当前系数乘以该系数;穿过右括号时,取栈顶元素,当前系数除以该元素。
当然,也可以不用这个栈,穿过右括号时再把其后面的系数读一遍就好了。
可以发现上述过程是O(n^2)的,可以通过预处理优化到O(n),(从后往前,用栈存系数,记录每个左括号位置对应的系数),但本题没有卡时间。

易错点

本题没有陷阱,着重注意循环边界条件即可。

收获

括号匹配的写法
循环边界条件一定要想清楚
BNF要会看

满分代码

//!边界的地方,左边和右边不一样
//!循环遍历问题,迭代器的边界处理和自增

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
const int N=1e3+10;
typedef pair<int,int> PII;

int n,stk[N],stktop;//stk为栈

int main(){
    cin>>n;
    while(n--){
        map<string,int>left,right;//clear?
        string s;
        cin>>s;
        int len=s.length();
        int i=0;
        while(s[i]!='='){
            char c=s[i];
            int mul=1;
            if(c=='+'){
                i++;
                continue;
            }
            else if(isdigit(c)){//发现系数
                mul=0;
                while(s[i]!='=' && isdigit(s[i])){
                    mul*=10;
                    mul+=s[i]-'0';
                    i++;
                }
            }
            //然后开始匹配化学式,并计算原子个数,别忘了乘以mul
            int j=i;
            while(s[j]!='=' && s[j]!='+'){ //右边可能要变
                if(isalpha(s[j])){ //括号外的情况
                    string ele;
                    if(isalpha(s[j+1]) && s[j+1]>='a' && s[j+1]<='z'){ //小写
                        ele=s.substr(j,2);
                        j+=2;
                    }
                    else ele=s.substr(j++,1);
                    //找系数
                    int submul=0;
                    if(isdigit(s[j])){
                        while(s[j]!='=' && isdigit(s[j])){
                            submul*=10;
                            submul+=s[j]-'0';
                            j++;
                        }
                    }
                    else submul=1;
                    //找到系数,更新答案
                    left[ele]+=mul*submul;

                }
                else{ //括号
                    if(s[j]=='('){
                        int k=j+1,pp=1;
                        while(pp){ //括号匹配
                            if(s[k]=='(')pp++;
                            else if(s[k]==')')pp--;
                            k++;
                        }
                        //成功匹配,找系数后缀
                        int kmul=0;
                        if(isdigit(s[k])){
                            while(s[k]!='=' && isdigit(s[k])){
                            kmul*=10;
                            kmul+=s[k]-'0';
                            k++;
                        }
                        }
                        else kmul=1;
                        //
                        stk[stktop++]=kmul;
                        mul *= kmul;

                    }
                    else if(s[j]==')'){
                        mul/=stk[--stktop];
                    }
                    j++;
                }
            }

            i=j;
        }

        i++;

        while(i<len){
            char c=s[i];
            int mul=1;
            if(c=='+'){
                i++;
                continue;
            }
            else if(isdigit(c)){//发现系数
                mul=0;
                while(i<len && isdigit(s[i])){
                    mul*=10;
                    mul+=s[i]-'0';
                    i++;
                }
            }
            //然后开始匹配化学式,并计算原子个数,别忘了乘以mul
            int j=i;
            while(j<len && s[j]!='+'){ //右边可能要变
                if(isalpha(s[j])){ //括号外的情况
                    string ele;
                    if(j+1<len && isalpha(s[j+1]) && s[j+1]>='a' && s[j+1]<='z'){ //小写
                        ele=s.substr(j,2);
                        j+=2;
                    }
                    else ele=s.substr(j++,1);
                    //找系数
                    int submul=0;
                    if(j<len && isdigit(s[j])){
                        while(j<len && isdigit(s[j])){
                            submul*=10;
                            submul+=s[j]-'0';
                            j++;
                        }
                    }
                    else submul=1;
                    //找到系数,更新答案
                    right[ele]+=mul*submul;

                }
                else{ //括号
                    if(s[j]=='('){
                        int k=j+1,pp=1;
                        while(pp){ //括号匹配,不用找边界因为已经确保匹配成功!
                            if(s[k]=='(')pp++;
                            else if(s[k]==')')pp--;
                            k++;
                        }
                        //成功匹配,找系数后缀
                        int kmul=0;
                        if(k<len && isdigit(s[k])){
                            while(k<len && isdigit(s[k])){
                            kmul*=10;
                            kmul+=s[k]-'0';
                            k++;
                            }
                        }
                        else kmul=1;
                        //
                        stk[stktop++]=kmul;
                        mul *= kmul;

                    }
                    else if(s[j]==')'){
                        mul/=stk[--stktop];
                    }
                    j++;
                }
            }

            i=j;
        }
        bool flag=1;
        for(auto i:left){
            if(right.count(i.fi) && i.se==right[i.fi]);
            else{
                flag=0;
                break;
            }
        }
        if(!flag){
            cout<<"N\n";
            continue;
        }

        for(auto i:right){
            if(left.count(i.fi) && i.se==left[i.fi]);
            else{
                flag=0;
                break;
            }
        }

        if(flag)cout<<"Y\n";
        else cout<<"N\n";


    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
无刷电机控制器程序MCU-STC12C5404是一种针对无刷电机控制器的专用程序。MCU代表微控制器单元,STC12C5404是一种型号,具有高性能和低功耗的特点。 该程序主要用于控制无刷电机,实现其运动控制和运动控制算法。无刷电机控制器利用电子技术和控制算法,驱动无刷电机进行运动,具有高效率、低噪音、高可靠性等优点。MCU-STC12C5404程序可以提供对无刷电机控制器的完整控制和管理。 该程序的功能主要包括: 1. 电机启动和停止控制:通过设定参数和逻辑判断,控制电机的启动和停止。 2. 电机转速控制:通过调节电机的驱动信号频率和占空比,实现电机转速的控制。 3. 转向控制:通过正确的相序控制,实现电机的正转、反转和制动等操作。 4. 过流和过热保护:监测电机电流和温度,并进行保护控制,防止电机过载和过热。 5. 过压和欠压保护:监测电机电源电压,并进行保护控制,防止电压异常损坏电机。 6. 通信接口:提供与外部设备(如上位机、传感器等)进行通信的接口。 MCU-STC12C5404程序不仅提供了针对无刷电机控制器的基本功能,还具有良好的可扩展性和定制性,可以适应不同的无刷电机控制需求。通过合理的配置和调试,可以实现高效稳定的无刷电机控制。该程序广泛应用于工业自动化、机器人、电动车辆等领域,为相关应用提供了稳定可靠的无刷电机控制解决方案。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值