csp-化学方程式

    基本思路:
    一个复杂的化学式:
    6A3(BC)4((DE)8((FG)7(HI)5)6)7
    开头"6"为整个化学式的系数
    去掉整体系数后,整体加上"()",使化学式变为一个大"项"
    (A3(BC)4((DE)8((FG)7(HI)5)6)7)
    简单处理后的化学式,可以用"项"的形式进行分析
    每一项的基本形式:
        1、A3 或者 (BC)4,每个大写字母代表一个元素符号,
    每个元素符号的组成:一个大写字母,或者大写字母开头,后面
    紧跟一个小写字母。
        2、每一项的后面紧跟该项的系数

    化学式这个大"项"可以看作一棵大树,内部的每个"()"代表子树,子树的
    系数为"()"后面紧跟的数字。据此可以分析该化学式。
    分析时,从后往前扫描,先扫描计算项的系数,遇到")"后,再递归扫描该项。
    每个元素的系数,为递归进入元素所在的"简单项"时,系数的累乘

#include<iostream>
#include<sstream>
#include<string>
#include<map>
#include<cstdio>
using namespace std;
map <string,int> mp[2];
int dfs(string item,int pos,int coef,int i)//返回:分析该item,最后返回item的前一个位置
//pos进入后为子项")"的前一个位置,出为子项"("前一个位置
{
	do
	{
		int subcoef=0,pow=1;
		while(isdigit(item[pos]))
			subcoef+=pow*(item[pos]-'0'),pow*=10,pos--;//数字从后往前读
		if(!subcoef)subcoef=1;
		if(item[pos]==')')//遇到"复子杂项",也就是"(AB)4"形式
			pos=dfs(item,pos-1,coef*subcoef,i);//pos为"复杂子项"前一个位置
		else//遇到"简单子项",也就是"A4"形式,直接截取出元素A,不需要递归
		{	
			int t=pos;//pos为元素小写尾字母
			while(islower(item[t]))t--;//t为元素大写首字母
			string element = item.substr(t,pos-t+1);
			mp[i][element]+=coef*subcoef;//i为前半部分还是后半部分,系数
			pos=t-1;//pos跳到该元素之前,继续分析
		}
	}while(item[pos]!='(');//遇到"("说明,当前项分析结束,开始回溯
	return pos-1;
}
void cal(int i,string formula)//取出化学式开头的整体系数,然后给剩余的部分前后加上(),变成"项"
{
	//计算系数
	int coef=0;
	int pos=0;
	while(isdigit(formula[pos]))coef=coef*10+formula[pos]-'0',pos++;//数字从前往后读
	if(!coef)coef=1;
	//剩余部分前后加上"()"
	formula.insert(pos,"(");//pos为第一个不为数字的位置
	formula+=')';
	dfs(formula,formula.length()-2,coef,i);
}
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		string equation;//方程式
		cin>>equation;
		stringstream ss1 (equation);
		string part;//等号前后两部分
		int i=0;
		while(getline(ss1,part,'='))
		{
			mp[i].clear();
			stringstream ss2(part);
			string formula;//化学式
			while(getline(ss2,formula,'+'))cal(i,formula);
			i++;
		}
		if(mp[0]==mp[1])cout<<"Y"<<endl;
		else cout<<"N"<<endl;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值