华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1013|回复: 1
打印 上一主题 下一主题

P2382 化学分子式

[复制链接]

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
跳转到指定楼层
楼主
发表于 2018-6-3 21:49:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P2382

题目背景
元首和元老正在共同努力学习化学,他们想让电脑帮助他模拟分子式减轻负担。请你帮他设计一个程序。

题目描述
你的任务是编写一个能处理在虚拟的化学里分子式的程序,在真正的化学里,每个分子式描述分子包括一个或者多个原子,但是,它可能没有真正的化学药品。

下面是原子符号和分子式的定义:

分子中一个原子由一个原子符号表示,原子符号由单个大写字母或者一个大写字母和一个小写字母组成。例如:H和He都是原子符号。

一个分子式是一个原子符号的非空序列,例如,HHHeHHHe是一个分子式,表示一个分子包括4个H和2个He。

为了方便起见,一段相同的式子,如x….x(n个X,2<=n<=99),可以被缩写为(X)n。如果X是一个原子符号,那么括号可以省略。例如,HHHeHHHe也可以写作H2HeH2He,(HHHe)2,(H2He)2,((H)2He)2。

分子式的定义可以用一种规范的语言描述。简而言之,分子式的语法描述如下:

分子--原子|原子数量|(分子)数字|分子 分子 原子—>大写字母|大写字母 小写字母

数字-2|3|4|5|……|99| 大写字母-A|B|……|Z| 小写字母-a|b|c|……|z| 在我们这个虚拟的化学里的每一个原子都有自己的原子质量,给你原子的质量,你的程序必须输出一个用分子式表示的分子质量。分子的质量定义为所有包括的原子的质量之和。例如,假设H和He的原子质量为1和4,那么(H2He)2的分子量为12。

输入输出格式
输入格式:
输入格式:

输入由两部分组成。第一部分是原子表,由一些行组成,每行包括一个原子符号、一个或者多个空格,以及该原子的原子质量(<=1000)。没有两行包含相同的原子符号。

第一部分最后仅包括一行字符串“END_OF_FIRST_PART”。

第二部分是一些行的序列。每行是一个分子式,不多于80个字符,而且不包括空格。一个分子最多包括10^5个原子,一些分子中的原子可能没有在原子表中出现。

最后一行仅一个零,表示输入结束。

输出格式:
输出格式:

输出时一些行的序列,和输入文件的第二部分行数相同。如果分子中的每一个原子都在原子表中出现,输出一个整数,并表示分子质量。否者输出UNKNOWN。不要输出多余的字符。

输入输出样例
输入样例#1:
H 1
He 4
C 12
O 16
F 19
Ne 20
Cu 64
Cc 333
END_OF_FIRST_PART
H2C
(MgF)2As
Cu(OH)2
H((CO)2F)99
0
输出样例#1:
14
UNKNOWN
98
7426
回复

使用道具 举报

13

主题

41

帖子

211

积分

中级会员

Rank: 3Rank: 3

积分
211
沙发
发表于 2018-6-7 12:38:41 | 只看该作者
  1. #include<iostream>
  2. #include<vector>
  3. #include<cstring>
  4. #include<string>
  5. #include<map>
  6. using namespace std;
  7. map<string,int> mp;
  8. int stack[101];
  9. int top=1;
  10. int main()
  11. {
  12.     while(1)
  13.     {
  14.         string s;
  15.         int num;
  16.         cin>>s;
  17.         if(s=="END_OF_FIRST_PART") break;
  18.         cin>>num;
  19.         mp[s]=num;
  20.     }
  21.     while(1)
  22.     {
  23.         top=1;
  24.         string s;
  25.         cin>>s;
  26.         if(s=="0") break;
  27.         int ll=s.size();
  28.         bool pp=1;
  29.         for(int i=0;i<ll;i++)
  30.         {
  31.             if(s[i]=='(') {top++;}
  32.             if(s[i]==')')
  33.             {
  34.                 if(!isdigit(s[i+1])) {stack[top-1]+=stack[top];stack[top]=0;top--;}
  35.                 else{
  36.                 int num=0;
  37.                 for(int j=i+1;j<ll;j++)
  38.                 {
  39.                     if(isdigit(s[j]))
  40.                     {
  41.                         num=num*10+s[j]-'0';
  42.                     }
  43.                     else break;
  44.                 }
  45.                 stack[top-1]+=stack[top]*num;
  46.                 stack[top]=0;
  47.                 top--;
  48.                 }
  49.             }
  50.             if(s[i]>='A'&&s[i]<='Z')
  51.             {
  52.                 string p="";
  53.                 p=s[i]+p;
  54.                 while(s[i+1]>='a'&&s[i+1]<='z') {
  55.                     p=p+s[i+1];
  56.                     i++;
  57.                 }
  58.                 if(mp.find(p)==mp.end()){cout<<"UNKNOWN"<<endl;pp=0;}
  59.                 if(!pp)
  60.                 {
  61.                         break;
  62.                 }
  63.                 if(!isdigit(s[i+1])) {stack[top]+=mp[p];}
  64.                 else
  65.                 {
  66.                     int num=0;
  67.                     for(int j=i+1;j<ll;j++)
  68.                     if(isdigit(s[j])) num=num*10+s[j]-'0';
  69.                     else break;
  70.                     stack[top]+=mp[p]*num;
  71.                 }
  72.             }
  73.         }
  74.         if(pp) cout<<stack[1]<<endl;
  75.         stack[1]=0;
  76.     }
  77.     return 0;
  78. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-11-2 22:41 , Processed in 0.096320 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表