P4711 「化学」相对分子质量

月赛的经典模拟题

模拟水题调到要死,但是还是能1A,还是很爽的。


这道题可以直接用scanf读入一行,用fgets会读入一个'\n',我不喜欢。

然后用一个变量从左到右扫一遍。

如果读到了大写字母,那么你现在肯定在读一个元素的名称。判断是否有小写字母,名字完了之后判断是不是有下标数字。

读数字是一件挺频繁的工作,建议封装成函数,很爽。

有一个难点是原子团,不过不难发现:用括号括起来的原子团一定会有下标!这是常识

处理原子团的时候应该单独计局部重量,到最后读完整个原子团的时候再加到总答案里面去。

最后的结晶水只需要读个数字走人就好了。如果没数字就根本不用读就是1。

没有数字默认的量就是1,这个最好设置着保险。

多debug看一下程序怎么跑,有时就能发现你的逻辑错误所在。

代码:

#include<cstdio>
#include<cstring>
#include<utility>
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<int,int> 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<int,int> pii = read(i + 4);
                    num = pii.first;
                    i = pii.second + 1;
                }
                else i += 2;
            }
            else if(ch[i + 1] == '_')// 一个字母但有数字的 
            {
                name[1] = 0;
                std::pair<int,int> 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<int,int> 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;
}
posted @ 2018-11-07 22:11  Garen-Wang  阅读(265)  评论(0编辑  收藏  举报