CCF:201912-3 化学方程式(JAVA版)
2020-03-06 本文已影响0人
巨鹿lx
解题思路
首先,用两个Map分别收集等号左右两边的元素,对比两个map的内容即可。那么问题就转化成了如何收集每一个化学式的信息。代码细节见注释
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class 化学方程式 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine();
while(n-->0) {
Map<String,Integer> ans1 = new HashMap<String , Integer>();
Map<String,Integer> ans2 = new HashMap<String , Integer>();
String s = scanner.nextLine();
String[] split = s.split("=");
String[] ls = split[0].split("\\+");
String[] rs = split[1].split("\\+");
for(String a : ls) {//处理等式左边
getOne(ans1,a);
}
for(String a: rs) {//处理等式右边
getOne(ans2,a);
}
for(Map.Entry<String , Integer> e : ans1.entrySet()) {//对比等式左右两边
int v = e.getValue();
String k = e.getKey();
int vv = ans2.containsKey(k)?ans2.get(k):-1;
if(!ans2.containsKey(k)||v!=vv) {
break;
}else {
ans2.remove(e.getKey());
}
}
if(ans2.size()==0)System.out.println("Y");
else System.out.println("N");
}
}
private static void getOne(Map<String, Integer> map,String s) {//先处理化学式系数
char[] a = s.toCharArray();
int l = 0;
int r = a.length - 1;
int x = 0;// 系数
while (a[l] <= '9' && a[l] >= '0')
x = x * 10 + a[l++] - '0';
getItem(a, l, r, map, x==0?1:x);//再处理化学式内容(注意是递归使用)
}
//记录一项
private static void getItem(char[] a, int l, int r, Map<String, Integer> map, int x) {
String e = "";
int num = 0;
while (l <= r && a[l] != ')') {
if(a[l]>='a'&&a[l]<='z') {//小写字母
e+=a[l++];
}else if (a[l] >= 'A' && a[l] <= 'Z') {//遇到大写字母意味着上一个元素结束
add(map, e, x, num);;
e ="" + a[l++];num = 0;
} else if (a[l] <= '9' && a[l] >= '0') {// 数字
num = num * 10 + a[l++] - '0';
} else {// 左括号
add(map, e, x, num);
e = "";num = 0;
int b[] = getnx(a, ++l, r);//得到右边界,倍数,下次需要处理的位置
getItem(a, l, b[0], map, x * b[1]);
l = b[2];
}
}
add(map, e, x, num);
}
/**
* 找到匹配表达式的系数和右边界,
* b0是表达式右边界(包含越界),b1是括号外数字(越界置1)
* b2是下次要开始的位置
*/
private static int[] getnx(char[] a, int l, int r) {
int count = 1,x = 0,rl = 0;
while (count != 0) {
if (a[l] == '(')count++;
if (a[l] == ')')count--;
l++;
}
rl = l-2;
while(l<=r&&a[l]<='9'&&a[l]>='0') x = x*10+a[l++]-'0';
return new int[] { rl, x==0?1:x ,l};
}
// 记录一个元素
private static void add(Map<String, Integer> map, String e, int x, int num) {
if(e.equals("")) return;
map.put(e, map.getOrDefault(e, 0) + (num == 0 ? 1 : num) * x);
}
}
附样例
2
888C222O+H2+Cl2=2HCl+(O888)(C888)222
88888Ba(OH)2(A(B(C)22)33)11=44444Ba(OH)2(A(B(C)22)33)11
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