CCF_Java_201912-3_化学方程式


时间限制: 1.0s
内存限制: 512.0MB

题目描述:

化学方程式,也称为化学反应方程式,是用化学式表示化学反应的式子。给出一组化学方程式,请你编写程序判断每个方程式是否配平(也就是方程式中等号左右两边的元素种类和对应的原子个数是否相同)。

本题给出的化学方程式由大小写字母、数字和符号(包括等号=、加号+、左圆括号和右圆括号)组成,不会出现其他字符(包括空白字符,如空格、制表符等),化学方程式的格式与化学课本中的形式基本相同(化学式中表示元素原子个数的下标用正常文本,如 H 2 O H_{2}O H2O写成H2O),用自然语言描述如下:

  • 化学方程式由左右两个表达式组成,中间用一个等号三连接,如2H2+O2=2H2O;
  • 表达式由若干部分组成,每部分由系数和化学式构成,部分之间用加号+连接,如2H2+O2、2H2O;
  • 系数是整数或空串,如为空串表示系数为1;
  • 整数由一个或多个数字构成;
  • 化学式由若干部分组成,每部分由项和系数构成,部分之间直接连接,如H2O、CO2、Ca(OH)2、Ba3(PO4)2;
  • 项是元素或用左右圆括号括起来的化学式,如H、Ca、(OH)、(P04);
  • 元素可以是一个大写字母,也可以是一个大写字母跟着一个小写字母,如H、O、Ca。

输入格式:

从标准输入读入数据。
输入的第一行包含一个正整数n,表示输入的化学方程式个数。
接下来n行,每行是一个符合定义的化学方程式。

输出格式:

输出到标准输出。
输出共n行,每行是一个大写字母Y或N,回答输入中相应的化学方程式是否配平。

输入样例1

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

输出样例1

N
Y
N
Y
Y
Y
Y
Y
Y
Y
N

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {

    static HashMap<String, Integer> Lelements = new HashMap<String, Integer>();
    static HashMap<String, Integer> Relements = new HashMap<String, Integer>();

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        String line = bf.readLine();

        int n = Integer.parseInt(line);

        for (int i = 0; i < n; i++) {
            line = bf.readLine();//分割方程式两边
            String[] formulas = line.split("\\=");
            
            FormulasSplit(formulas[0],Lelements);
            FormulasSplit(formulas[1],Relements);

            if(Lelements.equals(Relements)){
                System.out.println("Y");
            }else {
                System.out.println("N");
            }

            Lelements.clear();Relements.clear();
        }
    }

    static void FormulasSplit(String formula,HashMap<String,Integer> result){
        String[] elements = formula.split("\\+");
        for (String element : elements) {
            ArrayList<String> elemetnList = ElementsSplit(element);
            ElementsSum(elemetnList,result);
        }
    }

    static HashMap<String, Integer> ElementsSum(List<String> list ,HashMap<String,Integer> result) {//元素求和
        Stack<Integer> numbers = new Stack<Integer>();

        if (Character.isDigit(list.get(0).charAt(0))) {
            numbers.push(Integer.parseInt(list.get(0)));
        } else {
            numbers.push(1);
        }

        Collections.reverse(list);

        for (int i = 0; i < list.size(); i++) {
            int num = 1;

            if (Character.isDigit(list.get(i).charAt(0))) {
                numbers.push(Integer.parseInt(list.get(i)));
            } else if (Character.isUpperCase(list.get(i).charAt(0))) {
                for (Integer number : numbers) {
                    num *= number;
                }
                if (result.containsKey(list.get(i))) {
                    result.replace(list.get(i), result.get(list.get(i)) + num);
                } else {
                    result.put(list.get(i), num);
                }

                if (i>0 && Character.isDigit(list.get(i - 1).charAt(0)) ) {
                    numbers.pop();
                }
            } else if (list.get(i).equals("(")) {
                numbers.pop();
            }else if (i>0 && list.get(i).equals(")") && !Character.isDigit(list.get(i-1).charAt(0))) {
                numbers.push(1);
            }
        }
        return result;
    }

    static ArrayList<String> ElementsSplit(String str) {//分割为单个元素
        ArrayList<String> list = new ArrayList<String>();
        list.add(str.substring(0, 1));

        for (int i = 1; i < str.length(); i++) {

            char last = str.charAt(i - 1),cur = str.charAt(i);

            if (cur == '(' || cur == ')' || (Character.isDigit(cur) && !Character.isDigit(last)) || Character.isUpperCase(cur)) {
                list.add(list.size(), Character.toString(cur));
            } else if ((Character.isDigit(cur) && Character.isDigit(last)) || Character.isLowerCase(cur)) {
                list.set(list.size() - 1, list.get(list.size() - 1) + str.substring(i, i + 1));
            }
        }
        return list;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值