当前位置: 首页 > article >正文

acwing_5721_化学方程式配平

acwing_5721_化学方程式配平

这是一道T3的题目,操作起来可能有些棘手,但是耐下心来做一遍会有收获的!

下面是对于大佬的题解进行的注释

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 42;
double mat[N][N];
int n, m;
map<string, int> elei; // map中存放的是某种元素对应的标号(方程式中的每一个元素都有其标号,也就是系数矩阵的行号)
int index;

double eps = 1e-6;

void initMat() {
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            mat[i][j] = 0;
}

void getElement(string str, int &index, int in) {
    // index代表这个方程式中的第几号元素(方程式中的每一个元素都有其标号,也就是系数矩阵的行号),in 代表第几个物质
    str = str + '#'; // 方便对于最后一个物质进行处理
    string ele = "";
    int num = 0;
    bool complete = false;
    for (int i = 0; i < str.size(); i++) {
        char c = str[i];
        if (c >= '0' && c <= '9') {
            // 读到数字应该如何处理
            complete = true;
            num = num * 10 + c - '0';
        } else {
            // 读到字母应该如何处理
            if (complete) {
                // 如果元素已经读取完毕
                if (elei.find(ele) != elei.end()) {
                    // map中有这一个元素
                    mat[elei[ele]][in] = num;
                } else {
                    // map中没有这个元素
                    elei[ele] = index++;
                    mat[elei[ele]][in] = num; // 更新系数
                }
                ele = c;
                num = 0;
                complete = false;
            } else {
                // 如果元素还没有读取完,比如说al,只读入了一个a
                ele = ele + c;
            }
        }
    }
}

void _swap(int a, int b) {
    double tmp;
    for (int i = 0; i < m; i++) {
        tmp = mat[a][i];
        mat[a][i] = mat[b][i];
        mat[b][i] = tmp;
    }
}

void _sub(int a, int b) {
    // a行减去b行的适当倍数,使得a行第一列(子矩阵)元素为0
    double magni = mat[a][b] / mat[b][b];
    for (int i = b; i < m; i++) {
        // 遍历所有列做减法
        mat[a][i] -= mat[b][i] * magni;
    }
}

int main() {
    cin >> n;
    while (n--) {
        cin >> m; //物质的个数
        string str;
        initMat();
        elei.clear();
        index = 0;

        for (int i = 0; i < m; i++) {
            cin >> str;
            getElement(str, index, i);
        }
        // 做完上述操作之后,index代表该方程式中元素的个数
        for (int i = 0; i < m; i++) {
            // 对于矩阵的每一列进行遍历
            int j;
            for (j = i; j < index; j++) // 对于每一行进行遍历
                if (fabs(mat[j][i]) >= eps) break; // 找到第一个该列不为0的行号

            if (j == index) continue; // 如果该列全为0,那么对于除去该列的子矩阵重复上述判断
            else if (j != i) {
                //如果子矩阵中第一行第一列的元素为0,则将该行和与后面的某一个第一列非0的行交换,使第一行第一列的元素非0
                _swap(i, j);    //swap i j
            }

            for (j = i + 1; j < index; j++) {
                if (fabs(mat[j][i]) >= eps) {
                    _sub(j, i); //j line sub i
                }
            }
        }
        int k;
        for (k = 0; k < index && k < m; k++)
            if (fabs(mat[k][k]) <= eps) break; //判断某一行是否全为0,只需要判断对角线上元素即可,好好想想为什么
        if (k < m) cout << "Y" << endl;
        else cout << "N" << endl;
    }
    return 0;
}

注:

易错点

  • double有精度误差,不能直接和0进行比较!!!
  • _index的计算方法!!!

http://www.kler.cn/a/501108.html

相关文章:

  • 非PHP开源内容管理系统(CMS)一览
  • Full GC 日志
  • 硬件设计-七位半电压表硬件方案(下)
  • microPython搭建webServer--(一)使用microdot库实现基本页面显示
  • 【2024年华为OD机试】(C卷,100分)- 输出指定字母在字符串的中的索引(Java JS PythonC/C++)
  • nvim 打造成可用的IDE(2)
  • 预编译SQL
  • unity下载newtonsoft-json
  • Spring Boot性能提升的核武器,速度提升500%!
  • 【微服务】面试题 6、分布式事务
  • Agentless:OpenAI 采用的非代理框架
  • Postman接口测试基本操作
  • Linux常见命令总结
  • 循环神经网络(RNN):从基础到未来的应用
  • 美创科技获数字安全产业贡献奖
  • CSS语言的语法糖
  • 【软考】软件设计师
  • RV1126+FFMPEG推流项目(1)总体框架讲解
  • 基于mybatis-plus历史背景下的多租户平台改造
  • EFCore HasDefaultValueSql (续2 HasComputedColumnSql)
  • Spring中三级缓存详细讲解
  • Pytest-Bdd-Playwright 系列教程(完结篇):本框架的功能参数说明
  • JavaScript 数组及其常用方法
  • 《解锁鸿蒙Next系统人工智能语音助手开发的关键步骤》
  • 初学spring 框架(了解spring框架的技术背景,核心体现,入门案例)
  • Oracle 表分区简介