Molecular Formula

Time Limit : 2000/1000ms (Java/Other) Memory Limit : 60000/30000K (Java/Other)

Problem Description
Your mission in this problem is to write a computer program that manipulates molecular formulae in virtual chemistry. As in real chemistry, each molecular formula represents a molecule consisting of one or more atoms. However, it may not have chemical reality.
The following are the definitions of atomic symbols and molecular formulae you should consider.

An atom in a molecule is represented by an atomic symbol, which is either a single capital letter or a capital letter followed by a small letter. For instance H and He are atomic symbols.

A molecular formula is a non-empty sequence of atomic symbols. For instance, HHHeHHHe is a molecular formula, and represents a molecule consisting of four H’s and two He’s.

For convenience, a repetition of the same sub-formula X…X, where n is an integer between 2 and 99 inclusive, can be abbreviated to (X)n. Parentheses can be omitted if X is an atomic symbol. For instance, HHHeHHHe is also written as H2HeH2He, (HHHe)2, (H2He)2, or even ((H)2He)2.

The set of all molecular formulae can be viewed as a formal language. Summarizing the above description, the syntax of molecular formulae is defined as follows.

Molecule -> Atom | Atom Number | ( Molecule ) Number | Molecule Molecule
Atom -> CapitalLetter | CapitalLetter SmallLetter
Number -> 2 | 3 | 4 | . . . | 97 | 98 | 99
CapitalLetter -> A | B | C | . . . | X | Y | Z
SmallLetter -> a | b | c | . . . | x | y | z

Each atom in our virtual chemistry has its own atomic weight. Given the weights of atoms, your program should calculate the weight of a molecule represented by a molecular formula. The molecular weight is defined by the sum of the weights of the constituent atoms. For instance, assuming that the atomic weights of the atoms whose symbols are H and He are 1 and 4, respectively, the total weight of a molecule represented by (H2He)2 is 12.

Input
The input consists of two parts. The first part, the Atomic Table, is composed of a number of lines, each line including an atomic symbol, one or more spaces, and its atomic weight which is a positive integer no more than 1000. No two lines include the same atomic symbol.

The first part ends with a line containing only the string END_OF_FIRST_PART.

The second part of the input is a sequence of lines. Each line is a molecular formula, not exceeding 80 characters, and contains no spaces. A molecule contains at most 10^5 atoms. Some atomic symbols in a molecular formula may not appear in the Atomic Table.

The sequence is followed by a line containing a single zero, indicating the end of the input.

Output
The output is a sequence of lines, one for each line of the second part of the input. Each line contains either an integer, the molecular weight for a given molecular formula in the corresponding input line if all its atomic symbols appear in the Atomic Table, or UNKNOWN otherwise. No extra characters are allowed.

Sample Input
H 1
He 4
C 12
O 16
F 19
Ne 20
Cu 64
Cc 333
END_OF_FIRST_PART
H2C
(MgF)2As
Cu(OH)2
H((CO)2F)99
0

Sample Output
14
UNKNOWN
98
7426

处理多个括号比较麻烦,细心点if-else就可以了

C

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#pragma warning(disable:4996)
char atom[200][50];
int weight[200],sum[100],top;
int main(void)
{
	int digit,res,i,j,length,l=0,unknow=1;
	char input[81],temp[81];
	while(scanf("%s",input)&&strcmp(input,"END_OF_FIRST_PART"))//先读入原子名字和质量
	{
		strcpy(atom[l],input);
		scanf("%d",&weight[l]);
		l++;
	}
	while(scanf("%s",&input)&&input[0]!='0')
	{
		memset(sum,0,sizeof(sum));
		top=0;
		length=strlen(input);
		for(unknow=1,res=0,i=0,digit=0;i<=length-1;i++)
		{
			memset(temp,0,sizeof(temp));
			if(isupper(input[i]))  //如果第一个字母是大写的,如H,He
			{
				temp[0]=input[i];
				if(i+1<=length-1&&islower(input[i+1]))//判断第二个字母是不是小写,如He
				{
					temp[1]=input[i+1];
					for(j=0;j<l;j++)
						if(strcmp(temp,atom[j])==0)//找一下有没有这个原子的质量,没有就break
						{
							res=weight[j];
							break;
						}
					if(j==l)
					{
						printf("UNKNOWN\n");
						unknow=0;
						break;
					}
					if(i+2<=length-1&&isdigit(input[i+2]))//如果有原子的质量,继续判断,后面有2个数字,还是1个,还是没有
					{
						if(i+3<=length-1&&isdigit(input[i+3]))
						{
							digit=(input[i+2]-'0')*10+input[i+3]-'0';
							i+=3;
						}
						else
						{
							digit=input[i+2]-'0';
							i+=2;
						}
						sum[top++]=res*digit;
						continue;
					}
					sum[top++]=res;//将原子质量的值暂时存起来
					i++;
					continue;
				}
				for(j=0;j<l;j++)//这里是只有一个大写字母的情况,如H,O
					if(strcmp(temp,atom[j])==0)
					{
						res=weight[j];
						break;
					}
				if(j==l)
				{
					printf("UNKNOWN\n");
					unknow=0;
					break;
				}
				if(i+1<=length-1&&isdigit(input[i+1]))
				{
					if(i+2<=length-1&&isdigit(input[i+2]))
					{
						digit=(input[i+1]-'0')*10+input[i+2]-'0';
						i+=2;
					}
					else
					{
						digit=input[i+1]-'0';
						i++;
					}
					sum[top++]=res*digit;
					continue;
				}
				sum[top++]=res;
			}
			else if(input[i]=='(')//这里和如果是')'里的while循环一起看容易理解,先把这项标记为-1
				sum[top++]=-1;
			else if(input[i]==')')//根据题意,用括号的情况,括号后面一定有数字
			{
				res=0;
				if(i+2<=length-1&&isdigit(input[i+2]))
				{
					digit=(input[i+1]-'0')*10+input[i+2]-'0';
					i+=2;
				}
				else
				{
					digit=input[i+1]-'0';
					i++;
				}
				top--;  //因为我在前面用sum[top]存值的时候都有用top++,所以应该前退一项,从有意义的值开始累加
				while(sum[top]!=-1)
				{
					res+=sum[top];
					top--;//注意是top--
				}
				sum[top]=res*digit;
				top++;
			}
		}
		if(unknow)//前面有标记,如果一个原子的质量找不到,unknow会被赋值为0,如果unknow不为0,证明所有原子的质量都存在,进行累加,输出答案
		{
			for(res=0,i=0;i<top;i++)
				res+=sum[i];
			printf("%d\n",res);
		}
	}
	return 0;
}
发布了28 篇原创文章 · 获赞 4 · 访问量 1726

猜你喜欢

转载自blog.csdn.net/coffee__a/article/details/105175961