题解 P2382 【化学分子式】

· · 题解

这道题难度不大,模拟即可,但是有很多细节需要注意。

楼下大犇们都没怎么讲思路,那我来讲一讲。

【思路】

遇到化学分子式,学校里面对各种原子的整体,(就是括号里的东西),我们的科学老师告诉我们要把它看成一个大分子计算式量。

例如:

Ca(OH)_2

(Ca~40O~16,H~1)

我们就计算

40 + (16 + 1) * 2

那么问题就解决了,每次读到括号就递归的计算括号内分子的式量,乘上括号后面的系数(可能没有,要特判)。比如下面的式子:(现实中不存在)

A(BC(DE)_2)_3

我们就先递归

A + 3 * BC(DE)_2

然后继续算

A + 3 * (B + C + (D + E) * 2)

程序里先算D + E,然后是B + C + (D+E)*2,最后算A + 3 * (B + C + (D + E) * 2)

然后你就愉快的AC了。

至于存化学式,用mapstring随便离散搞搞,想手写离散的巨佬在下也会表示佩服。

```cpp #include <bits/stdc++.h> using namespace std; string END_MARK = "END_OF_FIRST_PART"; map <string, int> ele; bool ans = true; template <typename T> inline void read(T &x) { char c; x = 0; int fu = 1; c = getchar(); while(c > 57 || c < 48) { if(c == 45) { fu = -1; } c = getchar(); } while(c <= 57 && c >= 48) { x = (x << 3) + (x << 1) + c - 48; c = getchar(); } x *= fu; } template <typename T> inline void fprint(T x) { if(x < 0) { putchar(45); x = -x; } if(x > 9) { fprint(x / 10); } putchar(x % 10 + 48); } inline void first_part() { string s; int num; cin >> s; if(s == END_MARK) return; read(num); ele[s] = num; first_part(); } string a; // stack <char> t; int work(int l, int r) { if(l > r) return 0; // cout << l << ' ' << r << endl;//debug int tmp = l; if(a[l] == 40) { int tot = 1; while(tot > 0) { l ++; if(a[l] == 40) tot ++; if(a[l] == 41) tot --; } if(l == r) return work(tmp + 1, r - 1); else { int num = 0, tmpp = l; l ++; while(a[l] >= 48 && a[l] <= 57) { num = (num << 3) + (num << 1); num += a[l] - 48; l ++; } return work(tmp + 1, tmpp - 1) * (num? num : 1) + work(l, r); } } else { // cout << "Task2" << endl;//debug string ss; ss += a[l]; l ++; while(l <= r && a[l] >= 97 && a[l] <= 122) { ss += a[l]; l ++; } // cout << ss << endl;//debug if(!ele[ss]) return ans = false; if(l > r) { return ele[ss]; } int num = 0, tmpp = l; while(a[l] >= 48 && a[l] <= 57) { num = (num << 3) + (num << 1); num += a[l] - 48; l ++; } return work(tmp, tmpp - 1) * (num? num : 1) + work(l, r); } } int main() { first_part(); END_MARK = "0"; while(true) { ans = true; cin >> a; if(a == END_MARK) break; int ret = work(0, a.size() - 1); if(!ans) { printf("UNKNOWN\n"); } else{ fprint(ret); putchar('\n'); } } } ```