Kemija 题解

题目简述

输入 nn 个化学方程式,判断每个式子是否配平。配平的意义为 -> 前后每个原子的数量相等,也就是说符合质量守恒定理。

需要注意的是,以 + 为分隔符的每个小项中,第一个数字表示之后整个原子团的个数。这之后每个大写字母表示一个原子,若其后方跟了一个数字 xx,则表示有 xx 个该原子;如果没有,则表示有 11 个。并且感谢出题人,每个数字都是个位数,也就是只占一个字符

传送门:P8324 Kemija

题目分析

这是道模拟题,没有太大的思维难度,但想要以清晰简洁的代码实现出来还是需要一些构思的。这种构思的能力非常重要,尤其是在做思路复杂的题目时,我们不想被裹脚布般的代码所困扰。

因为所有原子都是大写字母,所以我们可以开一个大小为 2626cntcnt 数组表示每个原子的出现次数。-> 前的出现次数加进去,而之后的出现次数则从数组中减去。最后只要看看 cntcnt 中的值是否全部都是 00 即可。

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;

-> 的前后可以用变量 statusstatus 来表示,前为 11,后为 1-1。那么只要在原子出现次数加入 cntcnt 前乘以 statusstatus 就行了。

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;

再考虑单项开始的第一个数字。这个数字会影响后方许多原子的数量,所以我们要在一开始就将它的值记录在一个变量 bufbuf 中。之后在计算原子出现次数时,乘上 bufbuf

如何判断哪个数字代表了 bufbuf 呢,好在它的位置是有特点的,要么在整个方程字符串的第一个位置,要么在 + 后方,要么在 > 后方。

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;
}
全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务