化学方程式系列( 试 制 品)(挑战密室)

来源:互联网 发布:c语言中的system 编辑:程序博客网 时间:2024/03/29 15:11

试 制 品
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
ZZ大学的Dr.Kong最近发现实验室的很多试制品都已经用完。由于项目经费有限,为了节省,Dr.Kong决定利用实验室现有的试制品来生成所缺的试制品。为此,Dr.Kong连续几天通宵达旦整理出一份研究资料并让研究生Bill去实验并统计能产生多少种所缺的试制品。

Bill从头到尾翻完所有的资料,发现资料上写满了一大堆的化学方程式,上面除了大小写英文字母、数字、加号、等号外,再也没有其他的符号了。其中,每个方程式都是A1+A2+……+Ap=B1+B2+……+Bq的形式, 表示试制品A1,A2,……和Ap反应,生成了试制品B1,B2,……,Bq。其中Ai和Bj都是一种单质或化合物的化学式(长度不超过10个字符),1≤p,q ≤ 20 。每个方程式的总长不超过100个字符。有些试制品的化学式可能在现代社会的化学元素周期表里找不到,这是由于化学反应过程中可能又有物理反应导致的结果。

Bill头疼了,从哪个实验开始呢?你能帮助他吗?

输入
有多组测试数据。
第一行:N表示Dr.Kong写的化学方程式个数(1<=N<=400)
接下来有N行, 每一行是一个方程式.
再接下来的一行:M表示已有多少种试制品.(1<=M<=500)
接下来有M行,每一行是已有的一种试制品的化学式.
输出
第一行包含一个数T,表示可以产生多少种所缺的试制品.
在接下来的T行中,按ASCII码升序输出产生的试制品的化学式.
样例输入
4
H2O+Na=NaOH+H2
Cl2+H2=HCl
Fe+O2=Fe3O4
NaOH+HCl=H2O+NaCl
3
H2O
Na
Cl2
样例输出
4
H2
HCl
NaCl
NaOH
解题思路:将输入的化学方程式以等号为分界线,并用map映射将等号左边的映射成右边的(因为map会自动排序对这个题影响,所以我们要定义一个结构体map来保证原本的输入次序不变)然后再定义一个map——ma_1用来保存已有的反应物,a[]表示题目中给出的反应物,然后挨个遍历化学方程式中的反应物,如果反应物已经在ma_1中存在就将该反应物对应的生成物加入到ma_1中,同时也将所有的反应物加入到一个set集合里,然后将a中有从set中除去,最后直接输出就可以了

#include <iostream>#include <bits/stdc++.h>using namespace std;struct Node{    string str;    int n;    bool operator<(const Node &a) const{        return a.n>n;    }};int main(){    int N,M;    string a[1005];///用来存题目上已经给出反应物    map<Node,string> ma;///用来存反应物与生成物的一个映射    map<string,int> ma_1;///用来保存已有的反应物    string str;    set<string> S;///保存所有已有的反应物,并会自动按字典序排序    cin>>N;    Node ss;///临时变量,为了方便反应物与生成物的映射    for(int i=0;i<N;i++){///将每个化学方程式的反应物映射成生成物        cin>>str;        string str1,str2;int k;        for(int j=0;str[j]!='=';j++){            str1+=str[j];k=j;        }        ss.n=i;ss.str=str1;        for(int j=k+2;j<str.length();j++)///k+2是为了跳过“=”,后边的k1+=2和k2+=2是为了跳过“+”            str2+=str[j];        ma[ss]=str2;    }    cin>>M;    for(int i=0;i<M;i++)    {        cin>>str;ma_1[str]++;S.insert(str);a[i]=str;///输入已有的M种反应物,并将其加入到S和a中    }    map<Node,string>::iterator its;    for(its=ma.begin();its!=ma.end();its++)///遍历所有的化学方程式,看每个化学方程式中的反应物是不是都能在ma_1中找到,如果能则将该反应物对应的生成物加入到ma_1中去    {        Node str_temp=its->first;        string str_1;        int k1=0,flag=1;        while(k1<str_temp.str.length())        {            for(int i=k1;i<str_temp.str.length()&&str_temp.str[i]!='+';i++)            {                str_1+=str_temp.str[i];k1=i;            }            k1+=2;            if(!ma_1.count(str_1))  flag=0;            str_1.clear();        }        if(flag)        {            string str_t = ma[str_temp],str_t1;int k2=0;            while(k2<str_t.length())            {                for(int i=k2;i<str_t.length()&&str_t[i]!='+';i++)                {                    str_t1+=str_t[i];k2=i;                }                ma_1[str_t1]++;                k2+=2;                S.insert(str_t1);str_t1.clear();            }        }    }    set<string>::iterator it_s;    string str_sum[1005];int c=0;    for(it_s=S.begin();it_s!=S.end();it_s++)///遍历集合S将a中有的元素全部除去    {        int flag_1=1;        string temp=*it_s;        for(int i=0;i<M;i++)            if(temp==a[i])                flag_1=0;        if(flag_1)           str_sum[c++]=temp;    }    cout<<c<<endl;///输出有多少种新生成的化学物    for(int i=0;i<c;i++)        cout<<str_sum[i]<<endl;    return 0;}

挑战密室
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
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行,每行为一个化学方程式
输出
对于每个化学方程式输出一行:即密码。
样例输入
3
2C+O2=2CO
2NaOH+H2SO4=Na2SO4+2H2O
Ca2CO3+H2O=Ca2(OH)2+CO2
样例输出
0056
0142
0116

#include <iostream>#include <bits/stdc++.h>using namespace std;string a[10]={"N","C","O","Cl","S","H","Al","Ca","Zn","Na"};///先将所有的化学元素和它的相对原子质量一一对应好,方便后面用map映射int b[10]={14,12,16,35,32,2,27,40,65,23};int main(){    int T;cin>>T;    string str;    while(T--)    {        cin>>str;        string str_n;        int k1,t1=1;///用来表示化合物的系数        for(int i=0;i<str.length();i++)        {            if(str[i]=='=')                 k1=i;        }        for(int i=k1+1;i<str.length()&&str[i]!='+';i++)///只取化学方程式等号后的第一个化合物            str_n+=str[i];        stack<int> S;///用来进行运算        map<string,int> ma;        for(int i=0;i<10;i++)///将相对原子质量与相应的元素映射好            ma[a[i]]=b[i];        for(int i=0;i<str_n.length();i++)        {            if(isdigit(str_n[i])&&i==0)///判断等式后第一个字符是不是数字,如果是,将所有的数字转化成整数            {                t1=0;int k=i;                while(isdigit(str_n[k]))                {                    t1=t1*10+(str_n[0]-'0');k++;                }                i=k-1;                continue;            }            if(str_n[i]=='N'&&str_n[i+1]=='a')///如果是相应的单质将相应的相对原子质量入栈            {                   S.push(ma["Na"]);i++;            }            else if(str_n[i]=='C'&&str_n[i+1]=='l')            {                S.push(ma["Cl"]);i++;            }            else if(str_n[i]=='C'&&str_n[i+1]=='a')            {                S.push(ma["Ca"]);i++;            }            else if(str_n[i]=='A')            {                S.push(ma["Al"]);i++;            }            else if(str_n[i]=='Z')            {                S.push(ma["Zn"]);i++;            }            else if(str_n[i]=='N')                S.push(ma["N"]);            else if(str_n[i]=='C')                S.push(ma["C"]);            else if(str_n[i]=='O')                S.push(ma["O"]);            else if(str_n[i]=='S')                S.push(ma["S"]);            else if(str_n[i]=='H')                S.push(ma["H"]);            else if(str_n[i]=='(')///如果是左括号将0入栈                S.push(0);//            else if(str_n[i]==')')///遇到遇到右括号时将左括号之后的元素全部出栈求和,然后在将左括号出栈,将求得的和入栈            {                int s=0;                while(S.top()!=0)                {                    s+=S.top();                    S.pop();                }                S.pop();                S.push(s);            }            else if(isdigit(str_n[i]))///如果遇到数字,将数字转化成整数与栈顶整数相乘并压入栈中            {                int k=0;                while(isdigit(str_n[i]))                {                    char c=str_n[i];                    k=k*10+(c-'0');                    i++;                }                i--;                int s=S.top();                S.pop();                S.push(s*k);            }        }        int sum=0;///最后将栈中所有元素出栈并求和        while(!S.empty())        {            sum+=S.top();            S.pop();        }        printf("%04d\n",sum*t1);    }    return 0;}
0 0
原创粉丝点击