题目描述:
R组织的特工Dr. Kong 为了寻找丢失的超体元素,不幸陷入WTO密室。Dr. Kong必须尽快找到解锁密码逃离,否则几分钟之后,WTO密室即将爆炸。
Dr. Kong发现密室的墙上写了许多化学方程式中。化学方程式,也称为化学反应方程式,是用化学式表示物质化学反应的式子。化学方程式反映的是客观事实。因此书写化学方程式要遵守两个原则:一是必须以客观事实为基础;二是要遵守质量守恒定律。
化学方程式不仅表明了反应物、生成物和反应条件。同时,化学计量数代表了各反应物、生成物物质的量关系,通过相对分子质量或相对原子质量还可以表示各物质之间的质量关系,即各物质之间的质量比。对于气体反应物、生成物,还可以直接通过化学计量数得出体积比。例如:2NaOH+H2SO4=Na2SO4+2H2O
经过多次试探、推理,Dr. Kong发现密码是4位数字,就隐藏在化学方程式等号后的第一个分子中,其分子量就可能是密码(若分子量不足4位,前面加0)。
好在Dr. Kong还记得墙上各化学方程式用到的化学元素的原子量如下:
你能帮Dr. Kong尽快找到密码吗?
输入描述:
第一行: K,表示有K个化学方程式;
接下来有K行,每行为一个化学方程式
输出描述:
对于每个化学方程式输出一行:即密码。
样例输入:
复制
3
2C+O2=2CO
2NaOH+H2SO4=Na2SO4+2H2O
Ca2CO3+H2O=Ca2(OH)2+CO2
样例输出:
0056
0142
0116
题意就是计算等号后面的相对分子质量。
有括号(比如事例中的第一个) 就会想到用栈,利用栈的先进后出的特点,从等号后面开始算,如果是字母,对应的相对分子质量进栈,如果是数字,就乘上栈顶元素的相对分子质量,进栈,主要是括号,如果是左括号就记为-1,如果是右括号,计算栈里的分子质量和,直到遇到左括号,注意:括号后面有数字的话,要乘上对应的数字。最后在计算栈里所有元素和
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stack>
using namespace std;
int main() {
int N,i;
scanf("%d",&N);//代表有n组测试数据
getchar();//接收输入N后键入的空格,没有这个会出现答案错误
char s1[60];
while(N--) {
int temp1=-1,temp2;//temp1用来存放化学式前面的化学计量数。
memset(s1,'\0',sizeof(s1));//刚开始把他刷为‘\0',这样,即使后面的循环访问到len以后的区域也没有关系
stack<int>s;//定义一个名为s的栈,栈内元素类型为整型
gets(s1); //获取化学方程式
int len=strlen(s1);//测串长
for(i=0; i<len; i++) //如果是’=‘,break;,因为只求等号后面的第一个化学式
if(s1[i]=='=')
break;
if(s1[i+1]>='0'&&s1[i+1]<='9') { //计算化学式前面的化学计量数,
temp1=s1[i+1]-'0';
i=i+1;
}
for(i=i+1; i<len; i++) {
if(s1[i]=='+') break;//遇到加号说明组成第一个化学式的字符已经全部处理过了
else {
if(s1[i]=='O'||s1[i]=='S'||s1[i]=='H')//如果是O,S,H,他们不会与其他字符组合产生题目中所给出的搭配
//直接将该元素对应的相对原子质量压栈
{
int a;
if(s1[i]=='O')
a=16;
if(s1[i]=='S')
a=32;
if(s1[i]=='H')
a=2;
s.push(a);
}
if(s1[i]=='N') { //如果是N
if(s1[i+1]=='a') { //下一位是字符'a';
s.push(23);
i++;//23进栈
} else s.push(14); //否则是N,14进栈
}
if(s1[i]=='C') { //遇到字符C
if(s1[i+1]=='l') { //下一位是字符'l'
s.push(35);
i++;//是CL,35入栈
} else if(s1[i+1]=='a') { //下一位是字符'a'
s.push(40);
i++;//是Ca,40进栈
} else s.push(12); //不是上两种情况,就是C,让12进栈
}
if(s1[i]=='A') { //如果是A,说明是Al铝元素,直接让27进栈,i++
s.push(27);
i++;
}
if(s1[i]=='Z') { //如果是Z,说明是Zn锌元素,直接让65进栈,i++;
s.push(65);
i++;
}
if(s1[i]>='0'&&s1[i]<='9') { //遇到数字字符
temp2=s.top();//取栈顶元素
s.pop();//栈顶元素出栈
s.push(temp2*(s1[i]-'0'));//乘上计量数之后再入栈
}
if(s1[i]=='(')//如果是左括号,直接让-1进栈,-1只代表是遇到了一对括号
s.push(-1);
if(s1[i]==')') { //如果是右括号,让只要栈顶元素不是-1(不是左括号),就一直让sum1先加栈顶元素,在让栈顶元素出栈,最终sum1为括号内的化学式的质量
int sum1=0;//用于括号内元素的质量的累加
while(s.top()!=-1) { //没有遇到左括号,现在栈顶的元素都包含在括号中
sum1+=s.top();
s.pop();
}
s.pop();//最后把-1出栈,代表这一对括号处理完毕。
if(s1[i+1]>='0'&&s1[i+1]<='9') { //然后在考虑右括号后面有没有数字,有的或让数字乘sum1入栈
s.push(sum1*(s1[i+1]-'0'));
i=i+1;
} else
s.push(sum1);//右括号后面无数字,直接让sum1,入栈
}
}
}
int sum=0;
while(!s.empty()) { //最终栈中所有数字的和即为等式后第一个化学式的质量
sum=sum+s.top();
s.pop();
}
if(temp1!=-1)//如果有化学计量数
printf("%04d\n",temp1*sum);//一个化学计量数的质量乘上化学计量数
else
printf("%04d\n",sum);//否则,直接输出该化学式的质量即可,%04d是输出整数不足四位自动补0,
}
return 0;
}