nyoj - 挑战密室

题目描述:

R组织的特工Dr. Kong 为了寻找丢失的超体元素,不幸陷入WTO密室。Dr. Kong必须尽快找到解锁密码逃离,否则几分钟之后,WTO密室即将爆炸。

Dr. Kong发现密室的墙上写了许多化学方程式中。化学方程式,也称为化学反应方程式,是化学式表示物质化学反应的式子。化学方程式反映的是客观事实。因此书写化学方程式要遵守两个原则:一是必须以客观事实为基础;二是要遵守质量守恒定律。

化学方程式不仅表明了反应物、生成物和反应条件。同时,化学计量数代表了各反应物、生成物物质的量关系,通过相对分子质量或相对原子质量还可以表示各物质之间的质量关系,即各物质之间的质量比。对于气体反应物、生成物,还可以直接通过化学计量数得出体积比。例如:2NaOH+H2SO4=Na2SO4+2H2O

经过多次试探、推理,Dr. Kong发现密码是4位数字,就隐藏在化学方程式等号后的第一个分子中,其分子量就可能是密码(若分子量不足4位,前面加0)。

好在Dr. Kong还记得墙上各化学方程式用到的化学元素的原子量如下:

 

N

C

O

Cl

S

H

Al

Ca

Zn

Na

14

12

16

35

32

2

27

40

65

23

你能帮Dr. Kong尽快找到密码吗?

输入描述:

第一行: K,表示有K个化学方程式;接下来有K行,每行为一个化学方程式

输出描述:

对于每个化学方程式输出一行:即密码。

样例输入:

复制
32C+O2=2CO2NaOH+H2SO4=Na2SO4+2H2OCa2CO3+H2O=Ca2(OH)2+CO2

样例输出:

005601420116

提示:

2≤K≤8 ,化学方程式的长度不超过50, 所有原子,分子的数量不超过9.小括号最多一层.

来源:

第八届河南省程序设计大赛

分析:

字符串问题考虑的真的挺多的啊

有许多小细节,是我做这题收获的:

(1)map插入时在主函数里插

(2)char型数组赋值后再末尾加上:'\0'结束符

(3)getline读一行之前要把这一行之前的回车符用getchar()读掉

(4)处理麻烦的细节多的字符串题,要先规划好怎么判断,不然会WA好多次啊,嘤嘤嘤

思路:

把等号后的一个元素扣下来到char str数组中,然后遍历数组,分成几种情况:

(1)若第一个是数组,flag标记一下往下走

(2)只有一个字符

(3)当前字符代表的是字母,下一个也是

              a.这两个字母组成一个化学元素

              b.组不成一个化学元素

(4)当前字符代表的是字母,下一个代表的是数字

(5)当前元素是'(',我做题的时候,若符合(5),处理后直接略过')'和括号后的数字了

代码如下:

(代码真的又丑又长)

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<map>
#include<stack>
#include<algorithm>
using namespace std;

map<string,int> biao;

int main(){
    int cas,k,flag;
    string s;
    scanf("%d",&cas);
    getchar();
    biao.insert(pair<string,int>("N",14));
    biao.insert(pair<string,int>("C",12));
    biao.insert(pair<string,int>("O",16));
    biao.insert(pair<string,int>("Cl",35));
    biao.insert(pair<string,int>("S",32));
    biao.insert(pair<string,int>("H",2));
    biao.insert(pair<string,int>("Al",27));
    biao.insert(pair<string,int>("Ca",40));
    biao.insert(pair<string,int>("Zn",65));
    biao.insert(pair<string,int>("Na",23));
    while(cas--){
        char str[20];
        k=0,flag=0;
        getline(cin,s);

        for(int i=0;i<s.length();i++){
            if(s[i]=='=')flag=1;
            if(flag==0)continue;
            if(flag&&s[i]=='+')break;
            if(s[i]!='='){str[k++]=s[i];}
        }
        str[k]='\0';//要加结束字符啊,不然str[k]会有个不确定的值
        flag=0;

        int len=k;
        if(!isalpha(str[0]))flag=1;

        stack<int> num;
        stack<string> elem;
        for(int i=0;i<len;){
            if(flag&&i==0){i++;continue;}
            if(i+1==len&&isalpha(str[i])){
                num.push(1);
                string sub;
                sub=str[i];
                elem.push(sub);
                break;
            }
            else if(i+1<len&&isalpha(str[i])&&isalpha(str[i+1])){
                string sub;
                sub+=str[i];
                sub+=str[i+1];

                if(biao.count(sub)){
                    elem.push(sub);
                    if(i+2<len&&!isalpha(str[i+2])){num.push(str[i+2]-'0');i+=3;}
                    else {num.push(1);i+=2;}

                }
                else{
                    string sub;
                    sub=str[i];
                    elem.push(sub);
                    num.push(1);
                    sub=str[i+1];
                    elem.push(sub);
                    if(i+2<len&&!isalpha(str[i+2])){num.push(str[i+2]-'0');i+=3;}
                    else {num.push(1); i+=2;}
                }
            }
            else if(i+1<len&&isalpha(str[i])&&!isalpha(str[i+1])){
                string sub;
                sub=str[i];
                elem.push(sub);
                num.push(str[i+1]-'0');
                i+=2;
            }
            else if(str[i]=='('){
                int q=i+1;
                string sub;
                while(str[q]!=')'&&q<len){
                    sub=str[q++];
                    elem.push(sub);
                }
                int ci=str[q+1]-'0';
                int tmp=q;
                while(q-1>i){
                    num.push(ci);
                    q--;
                }
                i=tmp+2;
            }
        }
        string ee;
        int nn,ans=0;
        map<string,int>::iterator iter;
        while(!num.empty()&&!elem.empty()){
            ee=elem.top();elem.pop();
            nn=num.top();num.pop();
            iter=biao.find(ee);
            ans+=iter->second*nn;
        }
        if(flag)ans*=str[0]-'0';
        int p=10,y=1;
        while(ans/p){
            y++;p*=10;
        }
        while(y<4){
            printf("0");y++;
        }
        printf("%d\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37579232/article/details/80279697