有人已经实现了配平的方法,在此不再重复介绍。

https://www.cnblogs.com/Elfish/p/7631603.html

但是,上述的方法所提供的代码还是存在着问题,需要进一步修改。

首先,因为 frac 这个结构的成员函数和其它操作函数已被声明并定义至一个单一的文件里,

因此,首先要将它的声明和定义分开来。把 frac 结构体抽离至封装的类以外,作为前置声明。

因为原代码是直接 printf() 输出的,而我们需要的是获取它输出的结果。

所以,改变它输出的位置,声明一个 string ,将配好以后的结果直接赋值到 string 里。

最终代码实现:

[C++ 源代码]

 /* Exzh Cross Platfrom Toolkit (ECPT) Qt Version
* (This file is the part of the ECPT Project)
* Author: Exzh_PMGI
* E-mail: realexzh@gmail.com
* License: LGPL v3.0 / Exzh Commerical License
* Copyright: (C) Exzh_PMGI
* Qt Framework 5.10 has been tested successfully
* If you want to use the code for business,
* please contact me by my email.
*/ #include "exequationbalancer.h" #include <QDebug> int gcd(int x, int y) {
return x % y == ? y : gcd(y, x%y);
} int lcm(int x, int y) {
return x * y / gcd(x, y);
} frac createFrac(int a, int b)
{
frac tmp = { a,b };
return tmp;
} frac Abs(frac x) {
int p = x.a> ? x.a : -x.a, q = x.b> ? x.b : -x.b;
return createFrac(p, q);
} string exEquationBalancer::getResult(string inputstr)
{
strcpy(s,inputstr.c_str());
int lst = ;
for (int i = ;i<strlen(s);i++) {
if (i == strlen(s) - )scan(lst, i);
if (s[i] == '+' || s[i] == '=')
{
scan(lst, i - );
lst = i + ;
}
if (s[i] == '=')flag = -; //等号后面的系数变负
}
if (Solve())
for (int i = ;i <= c2 - ;i++)
ans[i] = M[i][N + ];
else output+="No Solution";
int tmp = lcm(ans[].b, ans[].b);
for (int i = ;i <= c2;i++)tmp = lcm(tmp, ans[i].b);
for (int i = ;i <= c2;i++)Ans[i] = ans[i].a*tmp / ans[i].b; //取分母Lcm,把分数变整数
for (int i = ;i <= c2;i++)
{
if (Ans[i]>) output+=to_string(Ans[i]);
for (int j = ;j<strlen(mat[i]);j++)
output+=mat[i][j];
if (i == c2)
{
return output;
qDebug()<<QString::fromStdString(output);
}
else if (i == c1) output+="=";
else output+="+";
}
} bool exEquationBalancer::Solve() { //解方程 (矩阵 高cnt,宽c2+1,c2+1列常数全0)
ans[c2] = ; //令最后一个解为1
for (int i = ;i <= cnt;i++) {
for (int j = ;j <= c2;j++)
M[i][j] = fun[i][j];
}
for (int i = ;i <= cnt;i++)
M[i][c2].a = -M[i][c2].a; //移到常数
//高斯消元过程
N = c2 - , K = cnt;
for (int k = ;k <= N;k++) {
frac maxm = createFrac(-, );
int maxi;
for (int i = k;i <= K;i++)
if (maxm<Abs(M[i][k]))
maxm = Abs(M[i][k]), maxi = i;
if (maxm == createFrac(, ))
return false;
if (maxi != k)
for (int j = ;j <= N + ;j++) {
swap(M[k][j], M[maxi][j]);
}
frac tmp = M[k][k];
for (int j = ;j <= N + ;j++)
M[k][j] = M[k][j] / tmp;
for (int i = k - ? : ;i <= K;i++) {
if (i == k)continue;
frac tmp = M[i][k];
for (int j = ;j <= N + ;j++)
M[i][j] = M[i][j] - tmp * M[k][j];
}
}
return true;
} void exEquationBalancer::scan(int l, int r) { //处理物质
c2++;
for (int i = ;i <= r - l;i++)mat[c2][i] = s[l + i]; //存下元素的名字
if (flag == )c1++; //统计一下反应物数量
int tmp = ; //tmp是小括号倍数
for (int i = l;i <= r;i++) {
if (s[i] == ')')tmp = ;
if (s[i] == '(') {
int j = i + ;while (s[j] != ')')j++; //找这个括号的范围
tmp = getint(j); //读")"右边的数字
}
if (s[i] >= 'A'&&s[i] <= 'Z') { //发现元素
int x = s[i] - 'A' + , y = ;
if (s[i + ] >= 'a'&&s[i] <= 'z') //看一眼是一个字母的还是两个的
y = s[i + ] - 'a' + ;
if (!Map[x][y])Map[x][y] = ++cnt; //判重
fun[Map[x][y]][c2] += flag * getint(i)*tmp; //把这个物质里的这种元素数量放进矩阵里,坐标(map[x][y],c2)
}
}
} int exEquationBalancer::getint(int pos) { //读数
pos++;
if (s[pos] >= 'a'&&s[pos] <= 'z')pos++;
if (s[pos]<'' || s[pos]>'')return ; //没数就是1
else {
int x = ;
while (s[pos] >= ''&&s[pos] <= '')x = x * + s[pos] - '', pos++; //读元素后面的数字
return x;
}
} void exEquationBalancer::print() {
output += to_string(N);
output += " ";
output += to_string(K);
output += "\n";
for (int i = ;i <= K;i++) {
for (int j = ;j <= N + ;j++)
{
output += to_string(M[i][j].a);
output += " ";
}
output += "\n";
}
output += "\n";
}

[C++ 头文件]

 /* Exzh Cross Platfrom Toolkit (ECPT) Qt Version
* (This file is the part of the ECPT Project)
* Author: Exzh_PMGI
* E-mail: realexzh@gmail.com
* License: LGPL v3.0 / Exzh Commerical License
* Copyright: (C) Exzh_PMGI
* Qt Framework 5.10 has been tested successfully
* If you want to use the code for business,
* please contact me by my email.
*/ #ifndef EXEQUATIONBALANCER_H
#define EXEQUATIONBALANCER_H #include <string>
#include "../exstdc++.h" using namespace std;
static string output;
int lcm(int x, int y);
int gcd(int x, int y); struct frac { //分数类
int a, b;
void reduce() {
int x = gcd(a, b);
a /= x, b /= x;
}
frac createFrac(int a, int b)
{
frac tmp = { a,b };
return tmp;
}
frac operator = (int x) {
a = x, b = ;
return *this;
}
frac operator = (const frac x) {
a = x.a, b = x.b;
reduce();
return *this;
}
frac operator + (const frac x) {
return createFrac(b*x.a + a * x.b, b*x.b);
}
frac operator - (const frac x) {
return createFrac(a*x.b - b * x.a, b*x.b);
}
frac operator * (const frac x) {
return createFrac(a*x.a, b*x.b);
}
frac operator / (const frac x) {
return createFrac(a*x.b, b*x.a);
}
bool operator < (const frac x) {
return a * x.b<b*x.a;
}
bool operator == (const frac x) {
return a * x.b == b * x.a;
}
void print() {
if (b == )
{
output += to_string(a);
output += "\n";
}
else
{
output += to_string(a);
output += "/";
output += to_string(b);
}
}
}; frac createFrac(int a, int b);
frac Abs(frac x); class exEquationBalancer
{
public:
string getResult(string inputstr); private:
bool Solve();
void scan(int l, int r);
int getint(int pos);
void print(); char s[];
int fun[][];
int Map[][]; //手动MAP
frac M[][]; //求解矩阵
frac ans[]; //解
int Ans[]; //整数解
int cnt, c1, c2, flag = , N, K; //cnt数元素,c1数反应物,c2总数 (未知数的数量)
char mat[][]; //存储物质的名称
}; #endif // EXEQUATIONBALANCER_H

[C++] 配平化学方程式算法的封装的更多相关文章

  1. 配平化学方程式的C++代码实现

    配平化学方程式的C++代码实现 纪念一下我今天写过了 20171006. (去年的这个时候我就有了这个大胆的想法, 当时的思路是:字符串处理->暴力搜系数,可是太年轻写不对,我那会还是个只会模拟 ...

  2. Python趣用—配平化学方程式

    不知不觉已经毕业多年了,不知道大家是否还记得怎么配平化学方程式呢?反正小编我是已经记不太清了,所以今天的文章除了分享如何用python配平化学方程式,顺带着还会复习 一些化学方程式的知识,希望广大化学 ...

  3. 用c++后缀自动机实现最大公共字符串算法,并封装成Python库

    后缀自动机的C++代码转自https://e-maxx.ru/algo/suffix_automata,其余封装为自写. 在C++文件同级目录建立setup.py文件,代码如下: # !/usr/bi ...

  4. 【HiJ1m】在NOIP2017前写过的有用的东西汇总

    http://www.cnblogs.com/Elfish/p/7544623.html 高级树状数组 http://www.cnblogs.com/Elfish/p/7554420.html BST ...

  5. CCF-CSP题解 201912-3 化学方程式

    判断化学方程式是否配平. 字符串处理. 有点编译原理递归下降法的感觉. 考场源码,比较粗糙. // INFO BEGIN // // User = 201911513451(陶杨) // Group ...

  6. 1.K近邻算法

    (一)K近邻算法基础 K近邻(KNN)算法优点 思想极度简单 应用数学知识少(近乎为0) 效果好 可以解释机器学习算法使用过程中的很多细节问题 更完整的刻画机器学习应用的流程 图解K近邻算法 上图是以 ...

  7. scikit-learn 支持向量机算法库使用小结

    之前通过一个系列对支持向量机(以下简称SVM)算法的原理做了一个总结,本文从实践的角度对scikit-learn SVM算法库的使用做一个小结.scikit-learn SVM算法库封装了libsvm ...

  8. Android 设计模式实战之关于封装计费代码库的策略模式详谈

    写在之前 这周生活上出现了很多的不如意,从周一开始就觉得哪里出现了问题,然后就是各种烦躁的情绪,后来事情还真是如预感的那样发生了,很是心痛,但也无可奈何,希望大家都好好珍惜自己身边的人:友人,亲人,家 ...

  9. 6种基础排序算法java源码+图文解析[面试宝典]

    一.概述 作为一个合格的程序员,算法是必备技能,特此总结6大基础算法.java版强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步:1.思想2.图 ...

随机推荐

  1. 第十四周(OOP版电子词典)

    /* *copyright(c) 2015,烟台大学计算机学院 *All rights reserved. *文件名:第十四周(OOP版电子词典) *作者:王忠 *完毕日期:2015.6.10 *版本 ...

  2. const与static类成员

    const成员函数作用1. 不能修改类的成员变量,同时不能调用类的非const成员函数.(const成员函数中,this的类型是一个指向const类类型对象的const指针,const成员函数返回*t ...

  3. Codeforces Round #250 (Div. 2)B. The Child and Set 暴力

    B. The Child and Set   At the children's day, the child came to Picks's house, and messed his house ...

  4. research plan

  5. 神经网络的结构汇总——tflearn

    一些先进的网络结构: # https://github.com/tflearn/tflearn/blob/master/examples/images/highway_dnn.py # -*- cod ...

  6. [LibreOJ NOIP Round #1] 旅游路线

    [题目链接] https://loj.ac/problem/539 [算法] 首先 , 我们用f[u][k]表示现在在景点u ,还有k元钱 , 最多能够走多少路 不难发现f[u][k] = max{ ...

  7. P3567 [POI2014]KUR-Couriers 主席树

    这个题比一般主席树还要简单,但是用来练习主席树再好不过了,在这里我再放一下主席树板子. 代码: #include<iostream> #include<cstdio> #inc ...

  8. [luoguP4142]洞穴遇险

    https://www.zybuluo.com/ysner/note/1240792 题面 戳我 解析 这种用来拼接的奇形怪状的东西,要不就是轮廓线\(DP\),要不就是网络流. 为了表示奇数点(即\ ...

  9. 面向对象软件工程与UML

    软件工程基本概念 软件危机 软件的功能.规模及复杂性与日俱增,软件的复杂性达到了它的开发者难以控制的程度 这种情况导致了严重的后果: 软件可靠性下降 开发效率低下 维护极为困难 这使软件开发者陷入困境 ...

  10. Akka源码分析-Remote-ActorSystem

    前面的文章都是基于local模式分析的,现在我们简要分析一下在remote模式下,ActorSystem的创建过程. final val ProviderClass: String = setup.g ...