【洛谷】【模拟+栈】P4711 「化学」相对分子质量

【题目传送门:】 [戳] (https://www.luogu.org/problemnew/show/P4711)

[算法分析:]

关于一个分子拆分后的产物,一共有三种情况:

  • 原子

  • 原子团

  • 水合物

关于原子的获取可以使用get_ele()函数,由于不是一位的元素就是两位的元素,只要看看这个大写字母的下一位是不是小写字母就行

返回获取的元素的string

关于系数的获取——使用函数get_num()——与快读的写法很接近,当没有系数的时候(处理后系数还是初始值没有被更新),系数是1

如何获取原子团

在出现左括号的时候使用get_group()函数

使用get_ele()不停地获取括号内的元素直到下一位是系数或者不是元素,

当下一位是系数的时候获取系数,并且获取这一位的元素,将获取的系数与获取的元素相乘。

其他:

  • 相对原子质量是实数,我们可以把他们都乘以10变成整数,有效地防止了被卡精度

  • 在处理水合物的时候记得水的相对分子质量不应是18而是180

  • 使用map来快速地获取每个元素的相对原子质量。

\([Code:]\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;

const int MAXN = 1000 + 1;

map<string, int> m;

string str;
int e, c;
int ele[MAXN], coe[MAXN];

void init() {
    m["H"] = 10;
    m["C"] = 120;
    m["N"] = 140;
    m["O"] = 160;
    m["F"] = 190;
    m["Na"] = 230;
    m["Mg"] = 240;
    m["Al"] = 270;
    m["Si"] = 280;
    m["P"] = 310;
    m["S"] = 320;
    m["Cl"] = 355;
    m["K"] = 390;
    m["Ca"] = 400;
    m["Mn"] = 550;
    m["Fe"] = 560;
    m["Cu"] = 640;
    m["Zn"] = 650;
    m["Ag"] = 1080;
    m["I"] = 1270;
    m["Ba"] = 1370;
    m["Hf"] = 1785;
    m["Pt"] = 1950;
    m["Au"] = 1970;
    m["Hg"] = 2010;
}

int get_num(int k) {
    int i = k + 2, num = 0;
    while(str[i] >= '0' && str[i] <= '9')
        num = (num << 3) + (num << 1) + str[i] - '0', ++i;
    if(!num) num = 1;
    coe[++c] += num;
    return i;
}

inline string get_ele(int &k) {
    string ret;
    ret += str[k];
    if(str[k + 1] >= 'a' && str[k + 1] <= 'z')
        ret += str[++k];
    return ret;
}

int get_group(int k) {
    int i = k + 1, num = 0;
    while(str[i] >= 'A' && str[i] <= 'Z' && str[i+1] != '_')
        num += m[get_ele(i)], ++i;
    if(str[i + 1] == '_' && str[i] != ')') {
        i = get_num(i + 1);
        i -= 4;
        num += m[get_ele(i)] * coe[c];
        i += 4;
        coe[c--] = 0;
    }
    
    ele[++e] = num;
    return i;
}

int get_h2o(int k) {
    int i = k + 1, num = 0;
    while(str[i] >= '0' && str[i] <= '9')
        num = (num << 3) + (num << 1) + str[i] - '0', ++i;
    if(!num) num = 1;
    ele[++e] = 180, coe[++c] = num;
    return i + 5;
}

int main() {
    init();
    cin >> str;
    int l = str.size();
    for(int i=0; i<l; ++i) {
        if(str[i] == '_') {
            i = get_num(i);
            continue;
        }
        if(str[i] == '(') {
            i = get_group(i);
            continue;
        }
        if(str[i] == '~') {
            i = get_h2o(i);
            continue;
        }
        if(str[i] >= 'A' && str[i] <= 'Z') {
            ele[++e] = m[get_ele(i)];
            if(str[i + 1] != '_') coe[++c] = 1;
        }
    }
    int ans = 0;
    for(int i=1; i<=e; ++i)
        ans += ele[i] * coe[i];
    cout << ans / 10.0;
}

猜你喜欢

转载自www.cnblogs.com/devilk-sjj/p/9202659.html