【洛谷】【模拟+栈】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;
}
posted @ 2018-06-20 11:01  DEVILK  阅读(873)  评论(0编辑  收藏  举报