nyoj 1236 挑战密室

挑战密室

时间限制: 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还记得墙上各化学方程式用到的化学元素的原子量如下:

                

你能帮Dr. Kong尽快找到密码吗?
输入
第一行: K,表示有K个化学方程式;
接下来有K行,每行为一个化学方程式
输出
对于每个化学方程式输出一行:即密码。
样例输入
3
2C+O2=2CO
2NaOH+H2SO4=Na2SO4+2H2O
Ca2CO3+H2O=Ca2(OH)2+CO2
样例输出
0056
0142
0116
提示
2≤K≤8 ,化学方程式的长度不超过50, 所有原子,分子的数量不超过9.小括号最多一层.
来源
第八届河南省程序设计大赛
解题思路:这个题就是让求等号后面出现的第一个分子的相对分子质量*分子个数,得出的结果如果不满四位,则前面补0,刚开始想到的是遍历,并依次判断,写着写着发现这样的话对于原子来说处理并不好,后来果断重写,使用栈来解决;

1、当遇到一个原子时,就把该原子入栈,继续往后遍历;

2、遍历遇到数字 i 时,说明该原子有 i 个,则把栈顶的原子弹出,并计算相对质量(sum1);

3、遇到左括弧时,将左括弧入栈;

4、在遇到右括弧之前重复上述步骤 1、2,(括弧内的原子质量sum2来存)

5、遇到右括弧计算括弧内剩下的所有原子的质量

6、最后sum1+sum2 就是总的相对分质量

请参看代码中的详解,如有不明白之处,尽请留言...

具体代码:
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;
//初始化,每个原子的相对质量对应Inia数组中的数字 
char Ins[10][3]={"N","C","O","Cl","S","H","Al","Ca","Zn","Na"};
int Inia[10]={14,12,16,35,32,2,27,40,65,23};
char s[55];
struct Node
{
	char str[3];
};
stack <Node> osta;
Node D;
int sum1=0,sum2=0;
int Find(char *str)//查找某个原子的相对质量 
{
	for(int i=0;i<10;i++)
		if(strcmp(str,Ins[i])==0)
			return Inia[i];
}
int fun(int sum,int i)
{
	if(s[i]>='A'&&s[i]<='Z' && s[i+1]>='a'&&s[i+1]<='z')
	{//是有两个字符组成的原子 
		D.str[0]=s[i],D.str[1]=s[i+1],D.str[2]='\0';
		osta.push(D);
	}
	else if(s[i]>='A'&&s[i]<='Z')
	{//单个字符组成的原子 
		D.str[0]=s[i],D.str[1]='\0';
		osta.push(D);
	}
	else if(s[i]>'0' && s[i]<='9')
	{//多个原子 
		Node p=osta.top();
		sum+=Find(p.str)*(s[i]-'0');
		osta.pop();
		return sum;
	}
	return 0;
}
int main()
{
	int T;
	char str[2];
	scanf("%d",&T);
	while(T--)
	{
		scanf("\n%s",&s);
		int flag_z=1,i=0;
		sum1=0; sum2=0;
		while(s[i++]!='=');//遍历到 = 结束
		if(s[i]>'0' && s[i]<='9')//判断等号后的第一位是不是数字,如果是的话,说明有多个分子
			flag_z=s[i++]-'0';//记录该分子有多少个 
		while(s[i]!='+' && i<strlen(s))
		{//对括弧外的每个原子质量进行求和 
			sum1+=fun(0,i);i++;
			if(s[i]=='(')
			{//有括弧的话,单独对括弧内的进行求解 
				D.str[0]='('; D.str[1]='\0';
				osta.push(D);//将左括弧压入栈,以便于作为下面判断括弧内原子是否计算完毕的条件 
				while(s[i]!=')')
					sum2+=fun(0,i),i++;
				Node p=osta.top();//取出栈顶的原子进行求解 
				osta.pop();
				while(strcmp(p.str,"(")!=0)
				{
					sum2+=Find(p.str);
					p=osta.top();
					osta.pop();
				}
				if(s[++i]>'0' && s[i]<='9')//说明括弧内的离子团有多个 
					sum2*=(s[i++]-'0');
			}
		}
		while(!osta.empty())
		{ //栈内剩余原子依次出栈求和 
			Node p=osta.top();
			sum1+=Find(p.str);
			osta.pop();
		}
		//分子个数*单个分子的相对分质量 
		int ans=flag_z*(sum1+sum2);
		if(ans<10)
			printf("000%d\n",ans);
		else if(ans<100)
			printf("00%d\n",ans);
		else if(ans<1000)
			printf("0%d\n",ans);
		else
			printf("%d\n",ans);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值