CCF-201912-3-化学方程式

题目好懂,但是坑多

题解:
这里用python的字典处理,元素为键,数量为值。所以思路就很清晰,判断等式两边的字典是否相等(很方便,用“==”就可以了)。先分开等式为左右两个表达式,用get_dict()得到各自的字典。再以加号分隔出一个个化学式,用get_part_dict()得到每个部分的字典。

重点:
1.嵌套,递归就好了;2.有的项会存在同级下有多个括号对的情况,比如Na(OH)(CO3);3.还有存在开头是括号的情况,(NaOH)。

处理这些问题,方法因人而异,我这里的方法get_part_dict(),直接遍历字符串,用一个空字符串接收每一个字符,遇到大写字母或遍历结束就说明到到分隔点,就要处理接收的字符串,统计,然后又清空。遇到左括号,就要找到对应的右括号,把里面的东西送到get_part_dict()里面,递归回一个字典,然后跟原字典合并,然后继续遍历后面的字符。

python100代码:

def get_dict(expr: str) -> dict:
    """得到某一边的字典(映射表)"""
    parts = expr.split('+')
    d = {}
    for part in parts:
        part_dict = get_part_dict(part)
        union(d, part_dict)
    return d


def get_part_dict(expr: str) -> dict:
    """得到某一部分的字典"""
    d, w = {}, 1
    i, ele = 0, ''
    while i < len(expr):
        c = expr[i]
        if c.isupper() and ele:
            if ele.isdigit():
                w = int(ele)
            else:
                k, v = get_item(ele)
                if k in d:
                    d[k] += v
                else:
                    d[k] = v
            ele = ''
        elif c == '(':
            cnt, end = 0, 0
            for j in range(i, len(expr)):
                cc = expr[j]
                if cc == '(':
                    cnt += 1
                elif cc == ')':
                    cnt -= 1
                if cnt == 0:
                    end = j
                    break
            sub = expr[i + 1:end]
            sub_dict = get_part_dict(sub)

            # 找ww,为每个元素后面的系数
            gap = len(expr)
            for j in range(end + 1, len(expr)):
                if not expr[j].isdigit():
                    gap = j
                    break

            ww = expr[end + 1:gap]
            ww = int(ww) if ww.isdigit() else 1
            update_dict(sub_dict, ww)
            union(d, sub_dict)
            i = gap
            continue
        ele += c
        i += 1

    # 处理结尾
    if ele:
        if ele.isdigit():
            w = int(ele)
        else:
            k, v = get_item(ele)
            if k in d:
                d[k] += v
            else:
                d[k] = v

    # 乘以总权值w
    update_dict(d, w)
    return d


def get_item(expr: str):
    """得到某个元素的元素名和数量"""
    gap = 0
    for i, c in enumerate(expr):
        if c.isdigit():
            gap = i
            break
    return (expr[:gap], int(expr[gap:])) if gap != 0 else (expr, 1)


def union(d1: dict, d2: dict):
    """合并两个字典:d2往d1中补"""
    if d2:
        for k, v in d2.items():
            if k in d1:
                d1[k] += v
            else:
                d1[k] = v


def update_dict(d, w):
    """更新字典:所有元素乘以系数w"""
    if w > 1 and d:
        for k in d:
            d[k] = d[k] * w


# 程序入口
if __name__ == '__main__':
    n = int(input())
    for i in range(n):
        left_d, right_d = map(get_dict, input().split('='))
        print('Y' if left_d == right_d else 'N')
        # print(d1)
        # print(d2)

# 样例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

# 样例2
# 1
# 77Na=23Na(CaaOH)3454(C((((()))))O3)22323

# 样例3
# 1
# 2(2Na)4+(Ca(OH)2)=(Ca(OH)2)+2(2Na)4

# 样例4
# 1
# Na(OH)(OH)2(CO3)2=Na(OH)(OH)2(CO3(NO3))2

你可能感兴趣的:(CCF)