题解 P2382 【化学分子式】
DPair
·
·
题解
这道题难度不大,模拟即可,但是有很多细节需要注意。
楼下大犇们都没怎么讲思路,那我来讲一讲。
【思路】
遇到化学分子式,学校里面对各种原子的整体,(就是括号里的东西),我们的科学老师告诉我们要把它看成一个大分子计算式量。
例如:
Ca(OH)_2
(Ca~40,O~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了。
至于存化学式,用map和string随便离散搞搞,想手写离散的巨佬在下也会表示佩服。
```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');
}
}
}
```