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还记得墙上各化学方程式用到的化学元素的原子量如下:
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
- 提示
- 2≤K≤8 ,化学方程式的长度不超过50, 所有原子,分子的数量不超过9.小括号最多一层.
- 来源
- 第八届河南省程序设计大赛
1 /* 2 Name: NYOJ--1236--挑战密室(第八届河南省程序设计大赛) 3 Copyright: ©2017 日天大帝 4 Author: 日天大帝 5 Date: 03/05/17 20:48 6 Description: 思路: 7 1.先处理开头的数字 8 2.每次处理一个元素,如果后面跟有数字,一起处理后入栈 9 3.遇到(之后每个元素都入栈一个( 10 4.遇到)先出队两个(因为两个元素只计算一次,却进栈了3个(、 11 5.将数值栈中的元素出栈累加 12 6乘以开头数字输出 13 比赛没调完,比赛调了一下直接A了o(╯□╰)o 14 */ 15 #include<stack> 16 #include<map> 17 #include<iomanip> 18 #include<iostream> 19 using namespace std; 20 map<string,int> mymap; 21 stack<int> num; 22 stack<char> op; 23 void init(){ 24 while(!num.empty())num.pop(); 25 while(!op.empty())op.pop(); 26 mymap["N"] = 14; 27 mymap["C"] = 12; 28 mymap["O"] = 16; 29 mymap["Cl"] = 35; 30 mymap["S"] = 32; 31 mymap["H"] = 2; 32 mymap["Al"] = 27; 33 mymap["Ca"] = 40; 34 mymap["Zn"] = 65; 35 mymap["Na"] = 23; 36 } 37 int check(char ch,char c){ 38 if(c == '!' || isdigit(c))return 1; 39 if(ch == 'O' || ch == 'S' || ch == 'H')return 1; 40 else if((ch == 'N' && c == 'a') || (ch == 'C' && c == 'l') || (ch == 'C' && c == 'a'))return 0; 41 else if(ch == 'N' || ch=='C')return 1; 42 else return 0; 43 } 44 int main(){ 45 ios::sync_with_stdio(false); 46 int k;cin>>k; 47 init(); 48 while(k--){ 49 string str;cin>>str; 50 int st = str.find("="); 51 string s = str.substr(st+1); 52 int en = s.find("+"); 53 s = s.substr(0,en); 54 s += "!";//加一个标记判断最后的元素是一个还是两个字符 55 int i=0; 56 int res = 0; 57 while(isdigit(s[i])){//将开始的数字提取出来单独处理 58 res *= 10; 59 res += s[i] - '0'; 60 i++; 61 } 62 if(res == 0)res = 1; 63 while(i < s.size()){//循环遍历字符串 64 if(isalpha(s[i])){//是字母 65 if(check(s[i],s[i+1]) == 0){//判断是否为两位的元素 66 string temp = ""; 67 temp += s[i]; 68 temp += s[i+1]; 69 int x = 0; 70 if(isdigit(s[i+2])){ 71 while(isdigit(s[i+2])){ 72 x *= 10; 73 x += s[i+2] - '0'; 74 i++; 75 } 76 } 77 if(x != 0)num.push(mymap[temp] * x); 78 else num.push(mymap[temp]); 79 if(!op.empty())op.push('('); 80 i += 2; 81 }else{//一位的元素 82 string temp = ""; 83 temp += s[i]; 84 int x = 0; 85 while(isdigit(s[i+1])){ 86 x *= 10; 87 x += s[i+1] - '0'; 88 i++; 89 } 90 if(x != 0)num.push(mymap[temp] * x); 91 else num.push(mymap[temp]); 92 if(!op.empty())op.push('('); 93 i++; 94 } 95 }else if(s[i] == '('){//(括号 96 op.push('('); 97 i++; 98 }else if(s[i] == ')'){//)括号 99 op.pop();op.pop(); 100 while(!op.empty()){ 101 int a = num.top();num.pop(); 102 int b = num.top();num.pop(); 103 num.push(a+b); 104 op.pop(); 105 } 106 i++; 107 if(isdigit(s[i])){ 108 int x = num.top();num.pop(); 109 x *= s[i] - '0'; 110 num.push(x); 111 } 112 i++; 113 } 114 else i++;//加!标记结尾了 115 } 116 int ans = 0; 117 while(!num.empty()){//将数字栈中所有数字出栈 118 ans += num.top(); 119 num.pop(); 120 } 121 cout<<setw(4)<<setfill('0')<<res*ans<<endl; 122 } 123 return 0; 124 }