化学方程式小程序

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


相关推荐
唐诺4 小时前
几种广泛使用的 C++ 编译器
c++·编译器
XH华4 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_4 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子4 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
冷眼看人间恩怨5 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
菜鸡中的奋斗鸡→挣扎鸡5 小时前
滑动窗口 + 算法复习
数据结构·算法
红龙创客5 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin5 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码5 小时前
Cmd命令大全(万字详细版)
python·算法·小程序