化学方程式小程序

brief introduction

相信大家上中学时都会被化学方程式折腾得死去活来,尤其是配平,怎么也算不对数字。于是我写出了这款近200行的自动配平程序,这是不是你们黑暗化学中的一丝光亮呢?

usage

正常化学式输入,每一种物质之间空一格,反应物/生成物输入完后空一格并打一个'-'(不带单引号)。一般情况下输入完后可以立刻出结果。需要保证系数在 [ 1 , 50 ] [1,50] [1,50] 之间。

code
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
string s[20], t[20];
int l[20][25], r[20][25], mid[20][25], ans[25], suml[25], sumr[25], le[25], le2[25], suml2[25];
bool vis[25], flag;
map<string, int> fy, sc, ele;
vector<int> to[25];
int a = 1, b = 1, tot, cnt, ok, o;
void dfs2(int step) {
	if(vis[step]) dfs2(step+1);
	if(step == b+1) {
		for(int i = 1;i <= tot;++i) 
			if(suml2[i]) return;
		for(int i = 1;i <= a;++i) {
			if(ans[i]!=1) printf("%d", ans[i]);
			cout << s[i];
			if(i != a) printf("+");
		}
		printf("==");
		for(int i = 1;i <= b;++i) {
			if(ans[a+i]!=1) printf("%d", ans[a+i]);
			cout << t[i];
			if(i != b) printf("+");
		}
		exit(0);
	}
	while(o) {
		flag = false;
		for(int i = 1;i <= tot;++i)
			if(le2[i] == 1) {
				int pos = to[i].size()-1;
				while(pos>=0 && to[i][pos]>=step && vis[to[i][pos]]) --pos;
				pos = to[i][pos];
				int x = suml2[i]/r[pos][i];
				if(vis[pos]) continue;
				flag = true;
				--o;
				if(suml2[i]%r[pos][i] || !suml2[i]) return;
				ans[a+pos] = x;
				vis[pos] = true;
				for(int j = 1;j <= tot;++j) {
					if(r[pos][j]) suml2[j] -= r[pos][j]*x, --le2[j];
					if(le2[j] == 1) ++o;
				}
				for(int j = 1;j <= tot;++j) 
					if(suml2[j] < 0) return;
			}
		if(!flag) break;
	}
	if(vis[step]) dfs2(step+1);
	else {
		int mn = 100;
		for(int i = 1;i <= tot;++i) mn = min(mn, suml2[i]/r[step][i]);
		for(int i = 1;i <= mn;++i) {
			ans[a+step] = i;
			bool fl = false;
			for(int j = 1;j <= tot;++j) {
				if(r[step][j]) {
					suml2[j] -= r[step][j]*i, --le2[j];
					if(le2[j]==1 && !fl) ++o, fl = true;
				}
			}
			dfs2(step+1);
			for(int j = 1;j <= tot;++j) 
				if(r[step][j]) {
					suml2[j] += r[step][j]*i, ++le2[j];
					if(le2[j]==1 && !fl) --o;
				}
		}	
	}
	return;
}
void dfs(int step) {
	if(step == a+1) {
		for(int i = 1;i <= tot;++i) suml2[i] = 0, suml[i] = 0, sumr[i] = 0, le2[i] = le[i];
		for(int i = 1;i <= b;++i) vis[i] = false;
		o = ok;
		for(int i = 1;i <= tot;++i)
			for(int j = 1;j <= a;++j)
				suml[i] += l[j][i]*ans[j], suml2[i] += l[j][i]*ans[j];
		dfs2(1);
		return;
	}
	for(int i = 1;i <= 50;++i) {
		ans[step] = i;
		dfs(step+1);
	}
}
int main () {
	while(cin >> s[a++] && s[a-1][0] != '-'); --a, --a;
	while(cin >> t[b++] && t[b-1][0] != '-'); --b, --b;
	for(int i = 1;i <= a;++i) {
		for(int j = 0;j < s[i].size();++j) {
			string str; str.clear();
			if(isupper(s[i][j])) {
				str += s[i][j];
				if(islower(s[i][j+1])) ++j, str += s[i][j];
				fy[str] = 1;
			}
		}
	}
	for(int i = 1;i <= b;++i) {
		for(int j = 0;j < t[i].size();++j) {
			string str; str.clear();
			if(isupper(t[i][j])) {
				str += t[i][j];
				if(islower(t[i][j+1])) ++j, str += t[i][j];
				if(fy[str] == 0) printf("Error!"), exit(0);
				sc[str] = 1;
			}
		}
	}
	for(auto it = fy.begin(); it != fy.end();++it) {
		ele.insert({it->first, ++tot});
		if(!sc[it->first]) printf("Error!"), exit(0);
	}
	for(int i = 1; i <= a;++i) {
		for(int j = 0;j < s[i].size();++j) {
			string str; str.clear();
			if(s[i][j] == '(') {
				++j; cnt = 0;
				while(s[i][j] != ')') {
					str.clear();
					str += s[i][j];
					if(islower(s[i][j+1])) ++j, str += s[i][j];
					++j;
					int num = 1;
					if(!isdigit(s[i][j])) mid[++cnt][ele[str]] = num;
					else {
						num = s[i][j]-'0';
						if(isdigit(s[i][j+1])) ++j, num = 10*num+s[i][j]-'0';
						++j; mid[++cnt][ele[str]] = num;
					}
				}
				++j;
				int num = s[i][j]-'0';
				if(isdigit(s[i][j+1])) ++j, num = 10*num+s[i][j]-'0';
				for(int j = 1;j <= cnt;++j)
					for(int k = 1;k <= tot;++k)
						l[i][k] += mid[j][k]*num;
			}
			else {
				str += s[i][j];
				if(islower(s[i][j+1])) ++j, str += s[i][j];
				int num = 1;
				if(!isdigit(s[i][j+1])) {l[i][ele[str]] += num; continue;}
				++j, num = s[i][j]-'0';
				if(!isdigit(s[i][j+1])) {l[i][ele[str]] += num; continue;}
				++j, num = 10*num+s[i][j]-'0';
				l[i][ele[str]] = num;
			}
		}
	}
	for(int i = 1; i <= b;++i) {
		for(int j = 0;j < t[i].size();++j) {
			string str; str.clear();
			if(t[i][j] == '(') {
				++j; cnt = 0;
				while(t[i][j] != ')') {
					str.clear();
					str += t[i][j];
					if(islower(t[i][j+1])) ++j, str += t[i][j];
					++j;
					int num = 1;
					if(!isdigit(t[i][j])) mid[++cnt][ele[str]] = num;
					else {
						num = t[i][j]-'0';
						if(isdigit(t[i][j+1])) ++j, num = 10*num+t[i][j]-'0';
						++j; mid[++cnt][ele[str]] = num;
					}
					to[ele[str]].push_back(i), ++le[ele[str]];
				}
				++j;
				int num = t[i][j]-'0';
				if(isdigit(t[i][j+1])) ++j, num = 10*num+t[i][j]-'0';
				for(int j = 1;j <= cnt;++j)
					for(int k = 1;k <= tot;++k)
						r[i][k] += mid[j][k]*num;
			}
			else {
				str += t[i][j];
				if(islower(t[i][j+1])) ++j, str += t[i][j];
				to[ele[str]].push_back(i), ++le[ele[str]];
				int num = 1;
				if(!isdigit(t[i][j+1])) {r[i][ele[str]] += num; continue;}
				++j, num = t[i][j]-'0';
				if(!isdigit(t[i][j+1])) {r[i][ele[str]] += num; continue;}
				++j, num = 10*num+t[i][j]-'0';
				r[i][ele[str]] = num;
			}
		}
	}
	for(int i = 1;i <= tot;++i)
		if(le[i] == 1) ++ok;
	dfs(1);
    return 0;
}
demonstration


相关推荐
奋斗的小花生3 小时前
c++ 多态性
开发语言·c++
pianmian13 小时前
python数据结构基础(7)
数据结构·算法
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
UestcXiye4 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
好奇龙猫5 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
霁月风5 小时前
设计模式——适配器模式
c++·适配器模式
sp_fyf_20245 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸6 小时前
链表的归并排序
数据结构·算法·链表
jrrz08286 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time6 小时前
golang学习2
算法