AC鸭玩化学方程式,有没有人帮我看一下

题目描述
AC鸭最近开始对化学方程式感兴趣了,他每天钻研25小时的化学方程式,现在“荣幸”的被选为了化学课代表,成为化学课代表后,它有了一个至高无上的权利:帮助检查其他同学的化学完成情况,所有的化学都由化学方程式组成,他的任务就是检查化学方程式是否平衡,化学方程式是一种使用符号和公式来表示化学反应的方法,在化学反应中,一组初始分子发生反应以产生另一组新的分子。

一个化学方程式分为左右两边,左边是初始分子的化学式,右边为产物分子的化学式。等式两边由 -> 分隔,在左边或者右边的不同分子用+分隔。分子是由原子构成,如果一个分子具有多个相同原子,则该原子的出现次数写在公式中的原子之后。例如,AC4B,表示该分子具有一个原子 A、4 个原子 C 和一个原子 B。

若在方程的一侧,一个分子不止出现一次,那么这个出现的次数写在该分子式的前面,例如:3AC4B 表示 3 个 AC4B 分子,总共有 3 个原子 A、12 个原子 C 和 3 个原子 B。

如果化学方程式的右侧和左侧原子每一种原子的数量相同,且左边原子的种类数与右边原子种类数相同,则称该化学方程式是平衡的。

你的任务是确定个化学方程式中的每一个化学方程式是否平衡。

输入
输入的第一行给出一个整数一表示有 n 个化学方程式。

接下来行。每一行给出一个字符串 S 一表示一个化学方程式,注意,原子均为大写英文字母组成,分子由原子和数字组成。

1



10
1≤n≤10



1000
S≤1000

题目保证单个化学方程式中元素的总个数在 int 范围之内。 题目保证每一个分子前面的数字是个位数,不保证其他数字是个位数

输出
输出行,对于每一个化学方程式,若平衡输出 YES,否则输出 NO。

样例
输入数据 1
7
A+B->AB
2AB+2AC+2BC->4ABC
2AB+A->3AB
2H2O+2CO2->2H2CO3
H2SO4->H2O4
NH3+H2SO4->NH4SO4
CH4+2O2->CO2+2H2O
输出数据 1
YES
YES
NO
YES
NO
NO
YES

【以下回答由 GPT 生成】

思路解析

首先,我们需要根据输入数据的格式进行解析,将每个化学方程式拆分成左右两部分。

然后,我们需要对每个方程式进行平衡检查。具体的步骤如下:

  1. 遍历每个方程式的左边部分,统计每种元素的数量,记录到一个字典中。字典的键为元素的名称,值为数量。
  2. 遍历每个方程式的右边部分,同样统计每种元素的数量,记录到另一个字典中。
  3. 检查两个字典是否相等,即左边和右边的元素数量是否相等。
  4. 如果左边和右边的元素种类数也相等,则说明化学方程式平衡,输出YES;否则,输出NO。

代码实现

#include <iostream>
#include <string>
#include <unordered_map>

using namespace std;

// 检查化学方程式是否平衡
string checkBalance(const string& equation) {
    // 找到等号的位置,将化学方程式分为左右两部分
    int arrowPos = equation.find("->");
    string leftStr = equation.substr(0, arrowPos);
    string rightStr = equation.substr(arrowPos + 2);

    // 统计左边和右边每种元素的数量
    unordered_map<char, int> leftElements;
    for (int i = 0; i < leftStr.size(); i++) {
        char c = leftStr[i];
        if (isalpha(c)) {
            // 元素名字
            char element = c;
            int count = 1;
            // 统计元素的数量
            while (i + 1 < leftStr.size() && isdigit(leftStr[i + 1])) {
                count = count * 10 + (leftStr[i + 1] - '0');
                i++;
            }
            leftElements[element] += count;
        }
    }

    unordered_map<char, int> rightElements;
    for (int i = 0; i < rightStr.size(); i++) {
        char c = rightStr[i];
        if (isalpha(c)) {
            // 元素名字
            char element = c;
            int count = 1;
            // 统计元素的数量
            while (i + 1 < rightStr.size() && isdigit(rightStr[i + 1])) {
                count = count * 10 + (rightStr[i + 1] - '0');
                i++;
            }
            rightElements[element] += count;
        }
    }

    // 检查左边和右边的元素数量是否相等
    if (leftElements == rightElements) {
        // 检查左边和右边的元素种类数是否相等
        if (leftElements.size() == rightElements.size()) {
            return "YES";
        }
    }

    return "NO";
}

int main() {
    int n;
    cin >> n;
    cin.ignore();

    for (int i = 0; i < n; i++) {
        string equation;
        getline(cin, equation);
        string result = checkBalance(equation);
        cout << result << endl;
    }

    return 0;
}

复杂度分析

代码的时间复杂度为O(n*m),其中n表示化学方程式的数量,m表示每个化学方程式的长度。由于题目中给出的条件是n不超过10个,m不超过1000,所以该算法的时间复杂度是可以接受的。



【相关推荐】


  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7599494
  • 除此之外, 这篇博客: 指针和数组试题解析(重置版)中的 小编,在这里想说一下,c语言的最后一节 C预处理,可能还需要一些时间,因为小编,昨天才下载了虚拟机 和 linux 系统,还没开始安装。所以无法着手写,因为 C预处理,vs2013很难表达,也就意味可能会讲不清楚。所以这篇文章可能需要点时间,再加上小编初期的文章,是没有排版的(而且可能有些错误,请大家以重置版为准),所以这几天我就把这些重新写。有兴趣的朋友可以看看。(ps:如果哪一天没有更新,意味着小编正在努力学习,为了能给大家呈现一片详细好懂的文章。) 部分也许能够解决你的问题。

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

供参考:

#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 1e3 + 5;
char s[MAXN];
int  a[MAXN];
bool ex(string x, int flag) 
{
    int cnt = 0, ret = 0, res = 0, i = 0;
    for (i = 0; i < x.length(); ++i) {
        if ((x[i] >= 'A' && x[i] <= 'Z') || (x[i] >= 'a' && x[i] <= 'z')) {
            if ((x[i] >= 'A' && x[i] <= 'Z'))
                cnt = cnt * 29 + (x[i] - 'A' + 1), ret++;
            else 
                cnt = cnt * 29 + (x[i] - 'a' + 1);
            if (ret >= 2)
                return false;
        }
        else 
            break;
    }
    for (; i < x.length(); ++i)
        if (x[i] >= '0' && x[i] <= '9')
            res = res * 10 + x[i] - '0';
        else 
            return false;
    if (res)
        flag *= res;
    a[cnt] += flag;
    return true;
}
int toint(string x) 
{
    string y;
    int cnt = 0, i, ret = 0;
    for (i = 1; i < x.length(); ++i) {
        if (cnt == 0 && x[i] == ')') {
            ++i;
            break;
        }
        if (x[i] == '(')cnt++;
        if (x[i] == ')')cnt--;
        y += x[i];
    }
    for (; i < x.length(); ++i)
        ret = ret * 10 + x[i] - '0';
    if (ret);
    else ret = 1;
    return ret;
}
string tostring(string x) {
    string y;
    int cnt = 0, i = 1, ret = 0;
    for (; i < x.length(); ++i) {
        if (cnt == 0 && x[i] == ')') {
            ++i;
            break;
        }
        if (x[i] == '(')cnt++;
        if (x[i] == ')')cnt--;
        y += x[i];
    }
    return y;
}
void slove(string x, int flag) 
{
    if (ex(x, flag))
        return;
    int pos = 0, res = 0, cnt = 0, i = 0, j = x.length() - 1;
    for (;; ++i) {
        if (x[i] >= '0' && x[i] <= '9')pos = pos * 10 + x[i] - '0';
        else 
            break;
    }
    if (pos)flag *= pos;
    string y;
    for (; i < x.length(); ++i) {
        if (x[i] == '(')cnt++;
        if (x[i] == ')')cnt--;
        if (cnt == 0 && (i + 1 == x.length() || (x[i + 1] >= 'A' && x[i + 1] <= 'Z') || x[i + 1] == '(')) {
            y += x[i];
            int b = flag;
            if (y[0] == '(') {
                b *= toint(y);
                y = tostring(y);
            }
            slove(y, b);
            y.clear();
        }
        else 
            y += x[i];
    }
}
int main() {
    int T;
    string t;
    scanf("%d", &T);
    while (T--) {
        memset(a, 0, sizeof(a));
        int flag = 1;
        scanf("%s", s);
        t.clear();
        int ls = strlen(s);
        for (int i = 0; i <= ls; ++i) {
            if (i == ls || s[i] == '+' || s[i] == '-' || s[i] == '>') {
                if (s[i] == '-') continue;
                slove(t, flag);
                t.clear();
                if (s[i] == '>')  flag = -1;
            }
            else 
                t += s[i];
        }
        int f = 1;
        for (int i = 0; i <= 1000; ++i) {
            if (a[i]) {
                f = 0; break;
            }
        }
        if (f)
            cout << "YES";
        else
            cout << "NO";
        if (T) cout << endl;
    }
    return 0;
}

//输入样例:
#if 0

7
A+B->AB
2AB+2AC+2BC->4ABC
2AB+A->3AB
2H2O+2CO2->2H2CO3
H2SO4->H2O4
NH3+H2SO4->NH4SO4
CH4+2O2->CO2+2H2O


11
H2+O2->H2O
2H2+O2->2H2O
H2+Cl2->2NaCl
H2+Cl2->2HCl
CH4+2O2->CO2+2H2O
CaCl2+2AgNO3->Ca(NO3)2+2AgCl
3Ba(OH)2+2H3PO4->6H2O+Ba3(PO4)2
3Ba(OH)2+2H3PO4->Ba3(PO4)2+6H2O
4Zn+10HNO3->4Zn(NO3)2+NH4NO3+3H2O
4Au+8NaCN+2H2O+O2->4Na(Au(CN)2)+4NaOH
Cu+As->Cs+Au

NO
YES
NO
YES
YES
YES
YES
YES
YES
YES
NO

#endif


#include <stdio.h>
#include <string.h>

int main() {
    int n;
    scanf("%d", &n);

    while (n--) {
        char s[1000];
        scanf("%s", s);

        int left_count = 0, right_count = 0;
        int left[26] = {0}, right[26] = {0};

        int i = 0;
        whilej] - '0';
                    j++;
                }
                i += j - 1;
            } else {
                int j = 0;
                while (s[i+j] >= '0' && s[i+j] <= '9') {
                    right_count *= 10;
                    right_count += s[i+j] - '0';
                    j++;
                }
                i += j - 1;
            }
            i++;
        }

        i++;
        while (s[i] != '\n') {
            if (s[i] >= 'A' && s[i] <= 'Z') {
                right[s[i]-'A']++;count += s[i+j] - '0';
                    j++;
                }
                i += j - 1;
            }
            i++;
        }

        if (left_count == right_count && memcmp(left, right, sizeof(left)) == 0) {
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }
    return 0;
}