欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CCF CSP2019.12 -- 化学方程式

程序员文章站 2022-05-12 14:56:44
...

CCF CSP2019.12 -- 化学方程式
CCF CSP2019.12 -- 化学方程式
CCF CSP2019.12 -- 化学方程式


可能在第六个测试测试点存在问题,但是很无奈,没找出来,样例数据都通过了。
个人代码如下,供参考

#include<iostream>
#include<string>
#include<string.h> 
#include<map>
#include<deque>
using namespace std;

//处理括号以及嵌套问题
void delete_brackets(map<string, int>& mp, string str, int cof) {
	deque<string> tmp_str;
	for (int i = 0; i < str.length();) {
		string tmp = "";
		tmp += str[i];
		if (str[i] >= 'A' && str[i] <= 'Z') {
			//一个大写字母后面跟着一个小写字母
			if (str[i + 1] >= 'a' && str[i + 1] <= 'z') {
				tmp += str[i + 1];
				++i;
			}
		}
		tmp_str.push_back(tmp);
		++i;
	}
	int tmp_cof = cof;
	while (!tmp_str.empty()) {
		if (tmp_str.front().c_str()[0] == '(') {
			int value = tmp_str.back().c_str()[0] - '0';
			if (value >= 2 && value <= 9) {//最后元素存在数字
				value = stoi(tmp_str.back());
				tmp_str.pop_back();  //删去数字
				if (tmp_str.back().c_str()[0] == ')') { //存在当前为“(...)num”该种形式时
					tmp_str.pop_front();  //删去左括号
					tmp_str.pop_back();  //删去右括号
					tmp_cof = tmp_cof * value;
				}
				else {//存在当前形式为“(...)element num”该种形式时
					int now_value = tmp_cof * value;
					map<string, int>::iterator iter;
					iter = mp.find(tmp_str.back());
					if (iter != mp.end())
						mp[tmp_str.back()] += now_value;
					else
						mp[tmp_str.back()] = now_value;
					tmp_str.pop_back();  //删去末尾元素
				}
			}
			else if (tmp_str.back().c_str()[0] == ')') {//最后位置不存在数字,即存在"(...)"该种形式时
				tmp_str.pop_front();  //删去左括号
				tmp_str.pop_back();  //删去右括号
			}
		}
		//存在该种"elemnet (...)..."形式时
		else if (tmp_str.front().c_str()[0] >= 'A' && tmp_str.front().c_str()[0] <= 'Z') {
			string tmp = tmp_str.front();
			tmp_str.pop_front();
			int num = tmp_cof;
			if (tmp_str.front().c_str()[0] - '0' >= 0 && tmp_str.front().c_str()[0] - '0' <= 9) {
				num = num * stoi(tmp_str.front().c_str());
				tmp_str.pop_front();//删去数字
			}
			map<string, int>::iterator iter;
			iter = mp.find(tmp);
			if (iter != mp.end())
				mp[tmp] += num;
			else
				mp[tmp] = num;
		}
	}
}

void Caculate_func(map<string, int>& mp, string str) {
	int coefficient = 1, i = 0; //系数
	if (str[i] - '0' >= 1 && str[i] - '0' <= 9) {
		string tmp = "";
		tmp += str[i];
		if (str[i + 1] - '0' >= 0 && str[i + 1] - '0' <= 9) {
			tmp += str[++i];
			if (str[i + 1] - '0' >= 0 && str[i + 1] - '0' <= 9) {
				tmp += str[++i];
			}
		}
		coefficient = stoi(tmp);
		++i;
	}
	while (i < str.length()) {
		if (str[i] >= 'A' && str[i] <= 'Z') {
			string tmp_str = "";
			tmp_str += str[i];
			if (i + 1 < str.length()) {
				//一个大写字母后面跟着一个整数
				if (str[i + 1] - '0' >= 0 && str[i + 1] - '0' <= 9) {
					string tmp = "";
					++i;
					tmp += str[i];
					if (str[i + 1] - '0' >= 0 && str[i + 1] - '0' <= 9)
						tmp += str[++i];
					map<string, int>::iterator iter;
					iter = mp.find(tmp_str);
					if (iter != mp.end())
						mp[tmp_str] += coefficient * stoi(tmp);
					else
						mp[tmp_str] = coefficient * stoi(tmp);
					++i;
				}
				//一个大写字母后面跟着一个小写字母
				else if (str[i + 1] >= 'a' && str[i + 1] <= 'z') {
					tmp_str += str[i + 1];
					i += 2;
					//判断小写字母后面是否有数字
					if (str[i] - '0' >= 0 && str[i] - '0' <= 9) {
						string tmp = "";
						tmp += str[i++];
						if (str[i] - '0' >= 0 && str[i] - '0' <= 9)
							tmp += str[i++];
						map<string, int>::iterator iter;
						iter = mp.find(tmp_str);
						if (iter != mp.end())
							mp[tmp_str] += coefficient * stoi(tmp);
						else
							mp[tmp_str] = coefficient * stoi(tmp);
					}
					//没有数字时
					else {
						map<string, int>::iterator iter;
						iter = mp.find(tmp_str);
						if (iter != mp.end())
							mp[tmp_str] += coefficient;
						else
							mp[tmp_str] = coefficient;
					}
				}
				//只有一个大写字母时
				else {
					map<string, int>::iterator iter;
					iter = mp.find(tmp_str);
					if (iter != mp.end())
						mp[tmp_str] += coefficient;
					else
						mp[tmp_str] = coefficient;
					++i;
				}
			}
			//作为最后一个原子时的判断
			else {
				map<string, int>::iterator iter;
				iter = mp.find(tmp_str);
				if (iter != mp.end())
					mp[tmp_str] += coefficient;
				else
					mp[tmp_str] = coefficient;
				++i;
			}
		}
		//遇到括号存在时
		else if (str[i] == '(') {
			int left_bracket = 0;
			int right_bracket = 0;
			string tmp_str = "";
			for (int j = i; j < str.length(); ++j) {
				tmp_str += str[j];
				if (str[j] == '(')
					++left_bracket;
				else if (str[j] == ')')
					++right_bracket;
				if (left_bracket == right_bracket) {
					i = j;
					++i;
					break;
				}
			}
			if (str[i] - '0' >= 0 && str[i] - '0' <= 9) {
				tmp_str += str[i];
				if (str[i + 1] - '0' >= 0 && str[i + 1] - '0' <= 9)
					tmp_str += str[++i];
				++i;
			}
			delete_brackets(mp, tmp_str, coefficient);
		}
	}
	return;
}

void Caculate(map<string, int>& mp, string str)//判断数目
{
	int add_num = 0;
	for (int i = 0; i < str.length(); ++i)
		if (str[i] == '+')
			add_num += 1;
	string* temp_str = new string[add_num + 1];//存储每一个化学式
	add_num = 0;
	for (int i = 0; i < str.length(); ++i) {
		if (str[i] == '+')
			add_num += 1;
		else
			temp_str[add_num] += str[i];
	}
	for (int i = 0; i <= add_num; ++i)
		Caculate_func(mp, temp_str[i]);
	delete[]temp_str;
}

bool Is_Judge(map<string, int>& mp_1, map<string, int>& mp_2) {
	if (mp_1.size() != mp_2.size())
		return false;
	for (auto it1 : mp_1) {
		auto it2 = mp_2.find(it1.first);
		if (it2 == mp_2.end())
			return false;
		else
			if (0 != memcmp(&it1.second, &it2->second, sizeof(int)))
				return false;
	}
	return true;
}

bool classification(map<string, int>& mp_1, map<string, int>& mp_2, string str) //以等号分段
{
	string head_str = "";
	string end_str = "";
	int len = 0;
	for (; str[len] != '='; ++len);
	head_str = str.substr(0, len);
	end_str = str.substr(len + 1, str.length() - len - 1);
	Caculate(mp_1, head_str);
	Caculate(mp_2, end_str);
	if (Is_Judge(mp_1, mp_2))
		return true;
	else
		return false;
}
int main()
{
	string str = "";//存化学式
	int total_num = 0;
	cin >> total_num;//总数读入
	while (total_num--) {
		map<string, int> mp_1;
		map<string, int> mp_2;
		cin >> str;//读入化学方程
		if (classification(mp_1, mp_2, str))//判断合法性
			cout << "Y" << endl;
		else
			cout << "N" << endl;
		mp_1.clear();
		mp_2.clear();
	}
	return 0;
}

测试结果
CCF CSP2019.12 -- 化学方程式


总结:
字符串真的很麻烦,还需要多加练习相关习题。