化学方程式小程序

news2024/9/21 17:48:07
brief introduction

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

usage

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

code
#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

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1316518.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智慧农业大数据可视化UI,数据展示平台(免费可视化大屏模版PS资料)

大屏幕展示方式可以实现信息的直观呈现与交互操作&#xff0c;使农业生产者能够一目了然地掌握有关农情、天气、土壤等数据信息&#xff0c;从而科学决策。智慧农业大数据可视化大屏是提升农业生产效益的一种重要工具。 现分享亩产效益指标、农业大数据可视化、农业数据展示平…

基于EasyExcel的数据导入导出

前言&#xff1a; 代码复制粘贴即可用&#xff0c;主要包含的功能有Excel模板下载、基于Excel数据导入、Excel数据导出。 根据实际情况修改一些细节即可&#xff0c;最后有结果展示&#xff0c;可以先看下结果&#xff0c;是否是您想要的。 台上一分钟&#xff0c;台下60秒&a…

QT Widget - 随便画个圆

简介 实现在界面中画一个圆, 其实目的是想画一个LED效果的圆。代码 #include <QApplication> #include <QWidget> #include <QPainter> #include <QColor> #include <QPen>class LEDWidget : public QWidget { public:LEDWidget(QWidget *pare…

前端传递参数,后端如何接收

目录 简单参数 传递方式 获取方式一 获取方式二 相关注解 实体参数 数组集合参数 传递方式 相关注解 获取方式一 获取方式二 日期参数 传递方式 相关注解 获取方式 json参数 传递方式 相关注解 获取方式 路径参数 传递方式 相关注解 获取方式 传递多个…

【Java系列】详解多线程(三)—— 线程安全(上篇)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习Java的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一…

心理测试网站源码,知己心理React心理健康测试

源码介绍 React心理健康测试网站源码&#xff0c;帮助需要的人更好地了解自已的心理健康状态和人格特征。 React可以在Vite中启用HMR&#xff0c;并且包含了几人EsLint规则。只需要使用react antd-mobile即可 轻松部署完成。

【JAVA日志框架】JUL,JDK原生日志框架详解。

前言 Java日志体系混乱&#xff1f;Java日志框架系列&#xff0c;清晰简洁整理好整个Java的日志框架体系。第一篇&#xff0c;JDK原生日志框架——JUL。 目录 1.概述 2.日志级别 3.配置 4.继承关系 1.概述 日志框架的核心问题&#xff1a; 日志是用来记录应用的一些运行…

C++ Qt开发:Tab与Tree组件实现分页菜单

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍tabWidget选择夹组件与TreeWidget树形选择组件…

Swift 响应式编程:简化 KVO 观察与 UI 事件处理 | 开源日报 No.110

ReactiveX/RxSwift Stars: 23.8k License: MIT RxSwift 是 Reactive Extensions 标准的 Swift 特定实现&#xff0c;它提供了 Observable 接口来表达计算的通用抽象。该项目旨在为 Rx API 提供真正以 Swift 为先的 API&#xff0c;并允许轻松地组合异步操作和数据流。其主要功…

K8s投射数据卷

目录 一.Secret 1.secret介绍 2.secret的类型 3.创建secret 4.使用secret 环境变量的形式 volume数据卷挂载 二ConfigMap 1.创建ConfigMap的方式 2.使用ConfigMap 2.1作为volume挂载使用 2.2.作为环境变量 三.Downward API 1.以环境变量的方式实现 2.Volume挂载 一.S…

Linux 中使用 docker 安装 Elasticsearch 及 Kibana

Linux 中使用 docker 安装 Elasticsearch 及 Kibana 安装 Elasticsearch 和 Kibana安装分词插件 ik_smart 安装 Elasticsearch 和 Kibana 查看当前运行的镜像及本地已经下载的镜像&#xff0c;确认之前没有安装过 ES 和 Kibana 镜像 docker ps docker images从远程镜像仓库拉…

HarmonyOS后台代理提醒

后台代理提醒 简介 随着生活节奏的加快&#xff0c;我们有时会忘记一些重要的事情或日子&#xff0c;所以提醒功能必不可少。应用可能需要在指定的时刻&#xff0c;向用户发送一些业务提醒通知。例如购物类应用&#xff0c;希望在指定时间点提醒用户有优惠活动。为满足此类业…

redis:四、双写一致性的原理和解决方案(延时双删、分布式锁、异步通知MQ/canal)、面试回答模板

双写一致性 场景导入 如果现在有个数据要更新&#xff0c;是先删除缓存&#xff0c;还是先操作数据库呢&#xff1f;当多个线程同时进行访问数据的操作&#xff0c;又是什么情况呢&#xff1f; 以先删除缓存&#xff0c;再操作数据库为例 多个线程运行的正常的流程应该如下…

云原生之深入解析Kubernetes Operator的最佳实践和最常见的问题分析

一、Kubernetes Operator 简介 Kubernetes Operator 是通过连接主 API 并 watch 时间的一组进程&#xff0c;一般会 watch 有限的资源类型。当相关 watch 的 event 触发的时候&#xff0c;operator 做出响应并执行具体的动作。这可能仅限于与主 API 交互&#xff0c;但通常会涉…

HiveSql语法优化二 :join算法

Hive拥有多种join算法&#xff0c;包括Common Join&#xff0c;Map Join&#xff0c;Bucket Map Join&#xff0c;Sort Merge Buckt Map Join等&#xff0c;下面对每种join算法做简要说明&#xff1a; Common Join Common Join是Hive中最稳定的join算法&#xff0c;其通过一个M…

selenium+xpath爬取二手房标题

贝壳找房标题爬取需要注意的是&#xff0c;在页面中间有一个小广告 而他就在ul的li下面&#xff0c;当我们进行title所以输出时&#xff0c;会报错。 所以在进行页面解析之前必须把广告叉掉&#xff0c;不然也把广告那一部分的li给爬取下来了 所以&#xff0c;我们&#xff0…

听GPT 讲Rust源代码--src/tools(13)

File: rust/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs 在Rust源代码中&#xff0c;路径为rust/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs的文件是为了处理Rust代码中的不一致实现问题而存在的。…

微服务实战系列之ZooKeeper(中)

前言 昨日博主的第一篇ZooKeeper&#xff0c;对它自身具备的能力做了初步介绍。书接上文&#xff0c;马不停蹄&#xff0c;我们继续挖掘它内在的美&#xff0c;充分把握它的核心与脉络。 揭秘ZooKeeper Q&#xff1a;集群一致性协同是如何进行的 我们讲到分布式&#xff0c;…

【MySQL】启动 和 连接 MySQL

启动停止 mysql安装成功后在cmd输入 net start mysql80 //启动 net stop mysql80 //停止 mysql连接 方式1. 通过客户端去连接 方式2.使用cmd去连接 描述&#xff1a;-u是指定 用户 -p是指定密码 mysql -u root -p password

Github 2023-12-16开源项目日报Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-16统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目2非开发语言项目2TypeScript项目1Jupyter Notebook项目1Go项目1PHP项目1JavaScript项目1C#项目1 精…