化学方程式小程序

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


相关推荐
QiLinkOS19 分钟前
【从实验室到商业战场:发明专利如何重塑科技与企业的共生生态】
大数据·c语言·数据结构·c++·人工智能·单片机·算法
Irissgwe1 小时前
c++11(lambda表达式与包装器、线程库)
c++·c++11·lambda表达式·线程库·包装器·互斥量库·条件变量库
小白兔奶糖ovo1 小时前
【Leetcode】231. 2的幂
linux·算法·leetcode
xiaoxiaoxiaolll1 小时前
《Light: Science & Applications》合并BIC实现80倍阈值单模运行:超紧凑光子晶体激光器新突破
人工智能·算法·机器学习
Peter·Pan爱编程1 小时前
14. Lambda 表达式:随手可写的函数对象
c++·算法·ai编程
-To be number.wan1 小时前
算法日记 | 暴力枚举
学习·算法
s_w.h2 小时前
【 linux 】动静态库的制作
linux·运维·服务器·算法·bash
不想写代码的星星2 小时前
从分支预测角度看 C++:为什么你的热循环慢得离谱?
c++
过期动态2 小时前
【LeetCode 热题 100】接雨水
java·数据结构·算法·leetcode·职场和发展
春日见2 小时前
5分钟入门强化学习之动态规划算法与实现
大数据·人工智能·python·算法·机器学习·计算机视觉