月赛的经典模拟题
模拟水题调到要死,但是还是能1A,还是很爽的。
这道题可以直接用scanf读入一行,用fgets会读入一个'\n'
,我不喜欢。
然后用一个变量从左到右扫一遍。
如果读到了大写字母,那么你现在肯定在读一个元素的名称。判断是否有小写字母,名字完了之后判断是不是有下标数字。
读数字是一件挺频繁的工作,建议封装成函数,很爽。
有一个难点是原子团,不过不难发现:用括号括起来的原子团一定会有下标!这是常识
处理原子团的时候应该单独计局部重量,到最后读完整个原子团的时候再加到总答案里面去。
最后的结晶水只需要读个数字走人就好了。如果没数字就根本不用读就是1。
没有数字默认的量就是1,这个最好设置着保险。
多debug看一下程序怎么跑,有时就能发现你的逻辑错误所在。
代码:
#include#include #include const int maxn = 105;char ch[maxn];int len;double mass(char ch1, char ch2){ if(ch1 == 'H' && ch2 == 0) return 1; else if(ch1 == 'C' && ch2 == 0) return 12; else if(ch1 == 'N' && ch2 == 0) return 14; else if(ch1 == 'O' && ch2 == 0) return 16; else if(ch1 == 'F' && ch2 == 0) return 19; else if(ch1 == 'N' && ch2 == 'a') return 23; else if(ch1 == 'M' && ch2 == 'g') return 24; else if(ch1 == 'A' && ch2 == 'l') return 27; else if(ch1 == 'S' && ch2 == 'i') return 28; else if(ch1 == 'P' && ch2 == 0) return 31; else if(ch1 == 'S' && ch2 == 0) return 32; else if(ch1 == 'C' && ch2 == 'l') return 35.5; else if(ch1 == 'K' && ch2 == 0) return 39; else if(ch1 == 'C' && ch2 == 'a') return 40; else if(ch1 == 'M' && ch2 == 'n') return 55; else if(ch1 == 'F' && ch2 == 'e') return 56; else if(ch1 == 'C' && ch2 == 'u') return 64; else if(ch1 == 'Z' && ch2 == 'n') return 65; else if(ch1 == 'A' && ch2 == 'g') return 108; else if(ch1 == 'I' && ch2 == 0) return 127; else if(ch1 == 'B' && ch2 == 'a') return 137; else if(ch1 == 'H' && ch2 == 'f') return 178.5; else if(ch1 == 'P' && ch2 == 't') return 195; else if(ch1 == 'A' && ch2 == 'u') return 197; else if(ch1 == 'H' && ch2 == 'g') return 201; else return 0;}std::pair read(int pos){ int ans = 0; while(pos < len) { if(ch[pos] < '0' || ch[pos] > '9') break; ans = ans * 10 + ch[pos] - '0'; pos++; } return std::make_pair(ans, pos);}double solve(){ len = strlen(ch); double total_weight = 0; bool in_yuanzituan = false; double yuanzituan_weight = 0; char name[2] = {0}; int num = 1; for(int i = 0; i < len; ) { int pos = i; if(ch[pos] >= 'A' && ch[pos] <= 'Z') { // 开始读入元素名 name[0] = ch[i]; num = 1; if(ch[i + 1] >= 'a' && ch[i + 1] <= 'z')// 两个字母的 { name[1] = ch[i + 1]; if(ch[i + 2] == '_') { std::pair pii = read(i + 4); num = pii.first; i = pii.second + 1; } else i += 2; } else if(ch[i + 1] == '_')// 一个字母但有数字的 { name[1] = 0; std::pair pii = read(i + 3); num = pii.first; i = pii.second + 1; } else// 一个字母还没数字 { name[1] = 0; i++; } //结算 if(in_yuanzituan) yuanzituan_weight += mass(name[0], name[1]) * num; else total_weight += mass(name[0], name[1]) * num; } else if(ch[pos] == '(') { in_yuanzituan = true; i++; } else if(ch[pos] == ')') { std::pair pii = read(pos + 3); num = pii.first; i = pii.second + 1; total_weight += yuanzituan_weight * num; in_yuanzituan = false; yuanzituan_weight = 0; } else if(ch[pos] == '~')// 后面是水合物 { num = 1; if(ch[pos + 1] >= '0' && ch[pos + 1] <= '9') { num = read(pos + 1).first; } total_weight += 18 * num; break; } } // how to do? return total_weight;}int main(){ scanf("%s", ch); double ans = solve(); int temp = ans; if(ans - temp < 1e-5) printf("%.0lf\n", ans); else printf("%.1lf\n", ans); return 0;}