题解 P4711 【「化学」相对分子质量】
Iowa_BattleShip
2018-06-19 14:24:52
这题么,绝对没有蓝题难度,我个人认为黄题封顶,毕竟这是少见的不毒瘤的模拟题。
这题很良心的没有括号嵌套,这样就不用递归那么麻烦了,直接读进来扫一遍即可,具体还是看代码吧。
```cpp
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
using namespace std;
char a[110],b[10];//a是读进来的整个字符串,b是临时字符数组,存当前元素
int l,ll;//l为a的长度,ll为b的长度
map<string,double>mp;//map大法好,存元素对应的相对原子质量
int cs(int &i)//类似快读,将字符转化为数字,同时将主函数的i同步扫过
{
int x=0;
for(;a[i]>='0'&&a[i]<='9';i++)
x=x*10+(a[i]-'0');
return x;
}
double js(int &i)//计算当前扫到的元素的相对原子质量,同样将主函数的i同步
{
double s=0;//记录质量
memset(b,0,sizeof(b));//清空临时字符数组
for(ll=-1;((a[i]>='A'&&a[i]<='Z')||(a[i]>='a'&&a[i]<='z'))&&(ll<0||(ll>=0&&(a[i]>='a'&&a[i]<='z')));i++)
b[++ll]=a[i];
//找到目前扫到的元素
//因为元素开头必是大写字母
//所以当扫到的字符不为小写字母(已将这个元素的首字母读入)说明当前元素已扫完
if(a[i]=='_')//若这元素后面有下标,就将数字读入并乘上该元素相对原子质量
{
i+=2;//直接跳过'_{'
s+=mp[b]*cs(i);
}
else//若没有下标,直接累加上该元素相对原子质量
{
s+=mp[b];
i--;
}
return s;
}
int main()
{
int i,o;
double s,k;
mp["H"]=1;//以下为初始化
mp["C"]=12;
mp["N"]=14;
mp["O"]=16;
mp["F"]=19;
mp["Na"]=23;
mp["Mg"]=24;
mp["Al"]=27;
mp["Si"]=28;
mp["P"]=31;
mp["S"]=32;
mp["Cl"]=35.5;
mp["K"]=39;
mp["Ca"]=40;
mp["Mn"]=55;
mp["Fe"]=56;
mp["Cu"]=64;
mp["Zn"]=65;
mp["Ag"]=108;
mp["I"]=127;
mp["Ba"]=137;
mp["Hf"]=178.5;
mp["Pt"]=195;
mp["Au"]=197;
mp["Hg"]=201;
scanf("%s",a);//合法字符串直接%s读入
l=strlen(a);//计算长度
for(i=0;i<l;i++)//直接扫
{
if(a[i]>='A'&&a[i]<='Z')//若为大写字母,说明扫到一个元素,直接累加上去
s+=js(i);
if(a[i]=='(')//若为左括号,则计算括号内的质量
{
i++;//跳过'('
for(k=0;a[i]!=')';i++)//因为没有括号嵌套或是水合物,里面必是各种元素,所以直接累加至遇到')'
k+=js(i);
if(a[i+1]=='_')//判断是否有下标
s+=k*cs(i+=3);//有则将数字乘上,i+=3是为跳过'_{'
else
s+=k;//没有就直接加上
}
if(a[i]=='~')//若有水合物
{
i++;//跳过'~'
if(a[i]=='H')//若为'H',说明只含一个水分子,直接累加
s+=18;//一个水分子的相对分子质量为18
else
s+=cs(i)*18;//不为'H'说明有数量,将其乘上即可
break;//因为水合物肯定在最后,所以直接跳出即可
}
}
o=s;//利用int强制转换来判断是否有.5
if(o==s)
printf("%d",o);
else
printf("%.1f",s);
return 0;
}
```