[代码已更新,满分代码请移步]CCF CSP 201912-3 化学方程式配平【Python 满分代码 】
[题目描述]
化学方程式,也称为化学反应方程式,是用化学式表示化学反应的式子。给出- -组
化学方程式,请你编写程序判断每个方程式是否配平(也就是方程式中等号左右两边的
元素种类和对应的原子个数是否相同)。
本题给出的化学方程式由大小写字母、数字和符号(包括等号=、加号+、左圆括
号(和右圆括号))组成,不会出现其他字符(包括空白字符,如空格、制表符等)。化
学方程式的格式与化学课本中的形式基本相同(化学式中表示元素原子个数的下标用.
正常文本,如H2O写成H20),用自然语言描述如下:
●化学方程式由左右两个表达式组成,中间用一-个等号=连接,如2H2+02=2H20;
●表达式由若干部分组成,每部分由系数和化学式构成,部分之间用加号+连接,
如2H2+02、2H20;
●系数是整数或空串,如为空串表示系数为1;
●整数由一个或多个数字构成; .
●化学式由若干部分组成,每部分由项和系数构成,部分之间直接连接,如H20、
C02、Ca(0H)2、 Ba3(P04)2;
●项是元素或用左右圆括号括起来的化学式,如H、Ca、(OH)、 (P04);
●元素可以是一个大写字母,也可以是一个大写字母跟着一一个小写字母,如H、0、
Ca。
非满分代码
问题出在哪里,我也不知道。
给的测试样例是全对的,官方test显示运行超时,60分。
另外一个版本的代码,显示运行错误,60分,218ms,猜测应该不是真正的资源不足,也许是某个地方进入了死循环?
但苦于样本不够,找不出问题所在,故发出来恳请大神能指点一二
这份代码是在Ubuntu 18 ,Python3.7的环境下写的,非标准的评测环境。
【2020年2月13日】在win下做了一点优化,变成70分了,也许真的是超时?
# -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
'''
11
Cu+As=Cs+Au
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
H2+O2=H2O
'''
class Elem:
def __init__(self,in_name,in_num=1):
self.name=in_name
self.num=in_num
def updateNum(self,in_num):
self.num*=in_num
class Form:
def __init__(self,in_str,in_Coef=1):
self.inStr=in_str
self.myCoef=in_Coef
self.list_Elem=[]
i=0
while i < len(self.inStr):
if self.inStr[i].isdigit():
if i == 0:
i, coeftemp = self.getNum(i)
self.myCoef *= coeftemp
continue
else:
print('May have ERROR in digit positon? Now inStr is {} , inStr[i] is {}.'.format(self.inStr,self.inStr[i]))
i+=1
continue
elif self.inStr[i].isupper():
i = self.disUpper(i)
continue
elif self.inStr[i]=='(':
i = self.disBrackest(i)
continue
else:
print('May have ERROR in current positon? Now inStr is {} ,inStr[i] is {}.'.format(self.inStr,self.inStr[i]))
i+=1
continue
if self.myCoef!=1:
#print('Mycoef is %d'%self.myCoef)
#print('before change:')
#self.printElem()
for i in range(len(self.list_Elem)):
self.list_Elem[i].updateNum(self.myCoef)
#print('after change:')
#self.printElem()
'''
print('\n')
self.printElem()
'''
def getNum(self, i):
temp_num=''
#print('i is %d'%i)
#print(self.inStr[i])
while i<len(self.inStr) and self.inStr[i].isdigit():
temp_num+=self.inStr[i]
#print('temp_num is %s'%temp_num)
i+=1
#print('temp_num is %s'%temp_num)
return i,int(temp_num)
def printElem(self):
for i in range(len(self.list_Elem)):
print('{}:{}'.format(self.list_Elem[i].name,self.list_Elem[i].num))
def disUpper(self, i):
name_temp = self.inStr[i]
i+=1
if i<len(self.inStr):
if self.inStr[i].isdigit():
i, numtemp = self.getNum(i)
self.list_Elem.append(Elem(name_temp,numtemp))
return i
elif self.inStr[i].islower():
name_temp += self.inStr[i]
if i + 1 < len(self.inStr) and self.inStr[i + 1].isdigit():
i += 1
i, numtemp = self.getNum(i)
self.list_Elem.append(Elem(name_temp,numtemp))
return i
else:
self.list_Elem.append(Elem(name_temp))
return i+1
else:
self.list_Elem.append(Elem(name_temp))
return i
else:
self.list_Elem.append(Elem(name_temp))
return i
def disBrackest(self, i):
l = i+1
r = self.inStr.rfind(')')
i=r
if i + 1 < len(self.inStr) and self.inStr[i + 1].isdigit():
i+=1
i, tempcoef = self.getNum(i)
self.list_Elem.extend(Form(self.inStr[l:r],tempcoef).list_Elem)
return i
else:
self.list_Elem.extend(Form(self.inStr[l:r]).list_Elem)
return i + 1
class E:
def __init__(self,in_str):
instr=in_str.split('=')
instr_l=instr[0].split('+')
instr_r=instr[1].split('+')
self.list_Elem_l=[Form(i).list_Elem for i in instr_l]
self.list_Elem_r = [Form(i).list_Elem for i in instr_r]
'''
for i in instr_l:
self.list_Elem_l.extend(Form(i).list_Elem)
for i in instr_r:
self.list_Elem_r.extend(Form(i).list_Elem)
#self.printElem(self.list_Elem_r)
'''
'''
print('L:')
self.printElem(self.list_Elem_l)
print('R:')
self.printElem(self.list_Elem_r)
'''
self.dict_l={}
self.dict_r={}
self.newDict(self.dict_l,self.list_Elem_l)
self.newDict(self.dict_r,self.list_Elem_r)
#print(self.dict_l)
#print(self.dict_r)
def newDict(self,in_dict,in_list):
for i in in_list:
if i.name in in_dict:
in_dict[i.name]+=i.num
else:
in_dict.setdefault(i.name,i.num)
def printElem(self,in_list):
for i in in_list:
print('{}:{}'.format(i.name,i.num))
def printResult(self):
if self.dict_l==self.dict_r:
print('Y')
else:
print('N')
'''
n=int(input())
list_in=[]
for i in range(n):
list_in.append(input())
for i in list_in:
E(i).printResult()
'''
n=int(input())
for i in range(n):
E(input()).printResult()
'''
用这个注释掉的for循环,最后一行要按回车才出结果,因此新增一个list接收输入
'''