Kemija 题解
题目简述
输入 个化学方程式,判断每个式子是否配平。配平的意义为 ->
前后每个原子的数量相等,也就是说符合质量守恒定理。
需要注意的是,以 +
为分隔符的每个小项中,第一个数字表示之后整个原子团的个数。这之后每个大写字母表示一个原子,若其后方跟了一个数字 ,则表示有 个该原子;如果没有,则表示有 个。并且感谢出题人,每个数字都是个位数,也就是只占一个字符。
传送门:P8324 Kemija
题目分析
这是道模拟题,没有太大的思维难度,但想要以清晰简洁的代码实现出来还是需要一些构思的。这种构思的能力非常重要,尤其是在做思路复杂的题目时,我们不想被裹脚布般的代码所困扰。
因为所有原子都是大写字母,所以我们可以开一个大小为 的 数组表示每个原子的出现次数。->
前的出现次数加进去,而之后的出现次数则从数组中减去。最后只要看看 中的值是否全部都是 即可。
int len=strlen(s+1),cnt[26];
for(int i=1;i<=len;i++){
//...
if(s[i]>='A'&&s[i]<='Z'){
//...
cnt[s[i]-'A']++;//...
}
//...
}
for(int i=0;i<26;i++)
if(cnt[i]){
cout<<"NE"<<endl;
return;
}
cout<<"DA"<<endl;
->
的前后可以用变量 来表示,前为 ,后为 。那么只要在原子出现次数加入 前乘以 就行了。
int len=strlen(s+1),cnt[26],status=1;
fill(cnt,cnt+26,0);
for(int i=1;i<=len;i++){
//...
if(s[i]>='A'&&s[i]<='Z'){
//...
cnt[s[i]-'A']+=status;//...
}
else if(s[i]=='-')status=-1,i++;
}
for(int i=0;i<26;i++)
if(cnt[i]){
cout<<"NE"<<endl;
return;
}
cout<<"DA"<<endl;
现在考虑如何计算原子的出现次数。影响出现次数的有两个数字,一个是可能出现单项开始的第一个数字,另一个则是每个原子后可能跟着的数字,先考虑后者。因为一定是个位数,所以直接判断原子的后一个字符是否为数字即可。
int len=strlen(s+1),cnt[26],status=1;
fill(cnt,cnt+26,0);
for(int i=1;i<=len;i++){
//...
if(s[i]>='A'&&s[i]<='Z'){
int num=1;
if(isdigit(s[i+1]))num=s[i+1]-'0';
cnt[s[i]-'A']+=status*num;//...
}
else if(s[i]=='-')status=-1,i++;
}
for(int i=0;i<26;i++)
if(cnt[i]){
cout<<"NE"<<endl;
return;
}
cout<<"DA"<<endl;
再考虑单项开始的第一个数字。这个数字会影响后方许多原子的数量,所以我们要在一开始就将它的值记录在一个变量 中。之后在计算原子出现次数时,乘上 。
如何判断哪个数字代表了 呢,好在它的位置是有特点的,要么在整个方程字符串的第一个位置,要么在 +
后方,要么在 >
后方。
int len=strlen(s+1),cnt[26],status=1,buf;
fill(cnt,cnt+26,0);
for(int i=1;i<=len;i++){
if(i==1||s[i-1]=='+'||s[i-1]=='>'){
buf=1; //新的小项开始了,初始化一下
if(isdigit(s[i]))buf=s[i]-'0',i++;
}
if(s[i]>='A'&&s[i]<='Z'){
int num=1;
if(isdigit(s[i+1]))num=s[i+1]-'0';
cnt[s[i]-'A']+=status*num*buf;
}
else if(s[i]=='-')status=-1,i++;
}
for(int i=0;i<26;i++)
if(cnt[i]){
cout<<"NE"<<endl;
return;
}
cout<<"DA"<<endl;
code
最后献上简短的 AC 代码:
#include<bits/stdc++.h>
#define N 1005
using namespace std;
int n,cnt[26];
char s[N];
void solve(){
fill(cnt,cnt+26,0);
cin>>(s+1);
int len=strlen(s+1),status=1,num,buf;
for(int i=1;i<=len;i++){
if(i==1||s[i-1]=='+'||s[i-1]=='>'){
buf=1;
if(isdigit(s[i]))buf=s[i]-'0',i++;
}
if(s[i]>='A'&&s[i]<='Z'){
num=1;
if(isdigit(s[i+1]))num=s[i+1]-'0';
cnt[s[i]-'A']+=num*buf*status;
}
else if(s[i]=='-')status=-1,i++;
}
for(int i=0;i<26;i++)
if(cnt[i]){
cout<<"NE"<<endl;
return;
}
cout<<"DA"<<endl;
}
int main(){
cin>>n;
while(n--)solve();
return 0;
}