CCF191203化学方程式满分

基本思路是:
1.根据‘=’号提取左右两侧。
2.根据‘+’提取各个部分
3.将各个部分为系数和化学式
4.然后再使用如下状态图解析化学式,如果有括号包裹的部分,将其整体递归一次。

这个题目就化学式的分析部分有点麻烦,这部分的解析画了一个简单的状态图,如下:

在这里插入图片描述

#include <iostream>
#include <vector>
#include <sstream>
using namespace std;

typedef struct Formula
{
	string name;
	int number;
}Formula;

typedef struct Item
{
	int coefficient;
	vector<Formula> formula;
}Item;

class Equeal
{
public:
	vector<Item> left;	
	vector<Item> right;
	void prase(string str);
    void split(string& src, char ch,string& des_s, string& des_e);
    void add_item(vector<Item>& vec, string str);
	void prase_fomula(Item& item, string fomula, int multiple);
	void add_element(Item& item, string str, int multiple);
	void calculate(vector<Item>& items, vector<Formula>& result);
	int compare(vector<Formula>& left_formuals, vector<Formula>& right_formuals);
};

void Equeal::prase(string str)
{
    string left_str , right_str;
    
    string item,leave;
    
	split(str, '=', left_str, right_str);
	
	do
	{
	    split(left_str, '+', item, leave);   
	    add_item(left, item);
	    left_str = leave;
	}while(!left_str.empty());
	
	do
	{
	    split(right_str, '+', item, leave);   
	    add_item(right, item);
	    right_str = leave;
	}while(!right_str.empty());
	
	
}

void Equeal::split(string& src, char ch,string& des_s, string& des_e)
{
    int pos;
    if((pos =  src.find(ch)) != src.npos)
    {
        des_s = src.substr(0, pos);
        des_e = src.substr(pos + 1);
    }
    else
    {
        des_s = src;
        des_e.erase();
    }
}

void Equeal::add_item(vector<Item>& vec, string str)
{
    string temp_str, formula_str;
    std::stringstream ss;
    int i, coefficient;
	Item item;
    
    for(i=0; i<str.size(); i++)
    {
        if(str[i] < '0' || str[i] > '9')
        {
            break;
        }
    }
    
    temp_str = str.substr(0, i);
    formula_str = str.substr(i);
    
    if(temp_str.empty())
    {
        coefficient = 1;
    }
    else
    {
        ss<<temp_str;
        ss>>coefficient;
    }
    
	item.coefficient = coefficient;

	prase_fomula(item, formula_str, 1);

	vec.push_back(item);
}

void Equeal::prase_fomula(Item& item, string fomula, int multiple)
{
	int i;
	int state = 0, bracket_count = 0;
	string element_str;
	

	for(i = 0; i<fomula.size(); i++)
    {
		switch(state)
		{
			case 0:
				if(fomula[i] >= 'A' && fomula[i] <= 'Z')
				{
					state = 2;
					element_str+=fomula[i];
				}
				else if(fomula[i] == '(')
				{
					element_str+=fomula[i];
					state = 1;
				}
				else
				{
					state = 0;
					element_str.erase();
				}
				break;
			case 1:
				if(fomula[i] == ')')
				{
					element_str+=fomula[i];

					if(bracket_count >0)
					{
						bracket_count--;
					}
					else
					{
						state = 4;
					}
				}
				else if(fomula[i] == '(')
				{
					element_str+=fomula[i];
					bracket_count++;
				}
				else
				{
					state = 1;
					element_str+=fomula[i];
				}
				break;
			case 2:
				if(fomula[i] >= 'a' && fomula[i] <= 'z')
				{
					state = 2;
					element_str+=fomula[i];
				}
				else if((fomula[i] >= 'A' && fomula[i] <= 'Z') || fomula[i] == '(')
				{
					add_element(item, element_str, multiple);
					element_str.erase();
					i--;
					state = 0;
				}
				else if(fomula[i] >= '0' && fomula[i] <= '9')
				{
					state = 3;
					element_str+=' ';
					element_str+=fomula[i];
				}
				else
				{
					state = 0;
					element_str.erase();
				}
				break;
			case 3:
				if(fomula[i] >= '0' && fomula[i] <= '9')
				{
					state = 3;
					element_str+=fomula[i];
				}
				else
				{
					add_element(item, element_str, multiple);

					element_str.erase();
					i--;
					state = 0;
				}
				break;
			case 4:
				if(fomula[i] >= '0' && fomula[i] <= '9')
				{
					state = 3;
					element_str+=' ';
					element_str+=fomula[i];
				}
				else
				{
					add_element(item, element_str, multiple);

					element_str.erase();
					i--;
					state = 0;
				}
				break;
			case 5:
				break;
			case 6:
				break;
			case 7:
				break;
			default:
				break;
		}
    }
    if(state != 0)
    {
		add_element(item, element_str, multiple);
	}
}

void Equeal::add_element(Item& item, string str, int multiple)
{
	string name,num_str;
	int num;
	Formula formula;

	if(str[0] == '(')
	{
		split(str, ' ', name, num_str);

		if(num_str.empty())
		{
			num = 1;
		}
		else
		{
			stringstream ss;
			ss<<num_str;
			ss>>num;
		}
		num*=multiple;

		name.erase(name.end() - 1);
		name.erase(0, 1);
		prase_fomula(item, name, num);
	}
	else
	{
		split(str, ' ', name, num_str);

		if(num_str.empty())
		{
			num = 1;
		}
		else
		{
			stringstream ss;
			ss<<num_str;
			ss>>num;
		}
		num*=multiple;
		int i;
		for(i=0; i< item.formula.size(); i++)
		{
			if(item.formula[i].name == name)
			{
				break;
			}
		}

		if(i >= item.formula.size())
		{
			formula.name  = name;
			formula.number = num;

			item.formula.push_back(formula);
		}
		else
		{
			item.formula[i].number += num;
		}
	}
}

void Equeal::calculate(vector<Item>& items, vector<Formula>& result)
{
	Formula formula;

	for(int i=0; i<items.size();i++)
	{
		for(int j=0;j<items[i].formula.size();j++)
		{
			int k;
			for(k=0; k<result.size(); k++)
			{
				if(result[k].name == items[i].formula[j].name)
				{
					break;
				}
			}
			if(k>=result.size())
			{
				formula.name = items[i].formula[j].name;
				formula.number = items[i].formula[j].number * items[i].coefficient;
				result.push_back(formula);
			}
			else
			{
				result[k].number += items[i].formula[j].number * items[i].coefficient;
			}
		}
	}
}

int Equeal::compare(vector<Formula>& left_formuals, vector<Formula>& right_formuals)
{
	for(int i=0; i<left_formuals.size();i++)
	{
		int j;
		for(j=0; j<right_formuals.size();j++)
		{
			if(left_formuals[i].name == right_formuals[j].name)
			{
				if(left_formuals[i].number != right_formuals[j].number)
				{
					return 0;
				}

				break;
			}
		}

		if(j >= right_formuals.size())
		{
			return 0;
		}
	}

	return 1;
}


vector<Formula> left_formuals;
vector<Formula> right_formuals;
Equeal equeal;

int main(void)
{
	
	int total;
	string str;
	
	cin>>total;
	
	for(unsigned int i=0; i<total; i++)
	{
		
		cin>>str;

		equeal.prase(str);
		equeal.calculate(equeal.left, left_formuals);
		equeal.calculate(equeal.right, right_formuals);
		if(equeal.compare(left_formuals, right_formuals) && equeal.compare(right_formuals, left_formuals) && equeal.right.size()>0)
		{
			cout<<'Y'<<endl;
		}
		else
		{
			cout<<'N'<<endl;
		}

		left_formuals.clear();
		right_formuals.clear();
		equeal.left.clear();
		equeal.right.clear();
	}

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值