首页 > ACM题库 > HDU-杭电 > hdu 2210 化学方程式[解题报告]C++
2014
01-04

hdu 2210 化学方程式[解题报告]C++

化学方程式

问题描述 :

还记得高中的化学方程式吗?当时化学课是我的最爱,老师常常需要我们用化学方程式来反应一种化学变化。但是粗心的我,常常在写化学方程式的时候,在一些细节上出问题。现在我们有很多的化学方程式,但是不知道其是否正确,需要你用编程来判断。
  首先我们以例子来说明下化学方程式的格式:
  2H2+O2==2H2O
  3Fe + 2O2==Fe3O4
  CaO + H2O == Ca(OH)2
1)  左边有N种化学品,右边有M种化学品,其中N>=1且M>=1,在每种化学品中,用一个大写字母或者一个大写字母加一个小写字母表示一种化学元素,每种化学元素在表示化学变化的符号“==”前后都出现。多于N>1和M>1的情况,相邻的两种化学品之间用一个“+”来连接。
2)  在每种元素(或者每种根,后面说明)后面出现的系数,是角标,表示这个元素或者根在这个化学品中出现的比例(主要和元素的最外层和次外层电子分布有关系,在这里不考虑具体的含义,只考虑格式),同时最先在这个化学品最前面的系数,表示这个化学方程式中,这种化学品参与化学反应的比例。根据守恒定理,前后出现的化学元素的个数必须相等。一般对于数字1都不用显式写出来(数据中也同样不会出现系数1),系数同样不为0(数据中也不出现)。
3)  对于一些由多个元素组成的串,表示一个“根”,如上面例子中的OH是一个氢氧根,也叫羟基。常常一个根必须由多个元素组成(单个元素不成为根),而在表示它们在化学品中出现的比例时,为了体现它们是一个小的部分,用括号包括起来(括号不能嵌套),再在其后加上系数,所以对于Ca(OH)2中,氧元素(O)与氢元素(H)同时出现两次,但是如果根只出现一次,可以加括号也可以不加,如NaOH。
4)  在一个化学方程式中,空格的出现一般是不受限制的,但是不能将同一个化学品内的元素以及所有与它们相关的系数分开,产生符号也不能分开。
5)  对于其他的一些特殊情况,如可逆化学方程式(事实上大部分的化学变化是可逆过程)用双向箭头表示,有些产生气体的分子后面需要用向上的箭头表示,在产生过程上还有可以加一些外界物理条件,产生沉淀需要说明等,我们不予考虑。

输入:

输入有多个case,每个case占一行,每行表示一个化学方程式

输出:

输入有多个case,每个case占一行,每行表示一个化学方程式

样例输入:

2H2+O2==2H2O

样例输出:

YES

#include <IOSTREAM>//vs运行完全正确,且getline输入完美。另,从vs复制过来的代码自带颜色,赞一个!
#include <STRING>
#include <CCTYPE>
using namespace std;
int times[2][52] = {0};
int side;
int x,y;
string s;
string::iterator i;
void count(char c,int add); 
int main()
{
      while(getline(cin,s))
      {
           side = 0;
           for (int j=0;j<2;j++)
           for (int k=0;k<52;k++)
                times[j][k] = 0;
           i = s.begin();
           x = y = 1;
           while (i!=s.end())
           {
                if (isalpha(*i))                                        //字母
                {
                     count(*i,x);
                }
                else if (isdigit(*i)&&(i==s.begin()||!isalpha(*(i-1))))
                {
                    x = int(*i)-48;
                }
                else if (isdigit(*i)&&isalpha(*(i-1)))
                {
                    y = int(*i)-48;
                    count(*(i-1),(y-1)*x);
                    if (islower(*(i-1)))
                    {
                        count(*(i-2),(y-1)*x);
                    }
                }
                else if (*i=='+')
                {
                     x = 1;
                }
                else if (*i=='=')
                {
                     side = 1;
                     x = 1;
                }
                else if (*i=='(')
                {
                     ;
                }
                else if (*i==')')
                {
                if ((i+1)!=s.end()&&isdigit(*(i+1)))
                {
                     y = int(*(i+1))-48;
                     string::iterator back = i-1;
                     int mid_y = 1;
                     while (*back!='(' )
                     {
                         if (isalpha(*back))
                         {
                              count(*back,(y-1)*x);
                              back--;
                         }
                         else if (isdigit(*back))
                         {
                              mid_y = int(*back)-48;
                              back-=2;
                              count(*(back-1),(y-1)*x*mid_y);
                              if (islower(*(back-1)))
                              {
                                   count(*(back-2),(y-1)*x*mid_y);
                                   back-=3;
                              }
                         }
                     }              
                }
           }
           i++;
      }
      int flag = 1;
      for(int k=0;k<52;k++)
      if(times[0][k]!=times[1][k]) flag = 0;
      if(flag) cout<<"YES" <<endl;
      else cout<<"NO" <<endl;
   }
   return 1;
}
void count(char c,int add)
{
     int index;
     if(c>65&&c<90) index = int(c)-65;
     else index = int (c)-97+26;
     times[side][index]+=add;
}

解题转自:http://blog.csdn.net/xiaogmail/article/details/8980540


  1. #include <stdio.h>
    int main()
    {
    int n,p,t[100]={1};
    for(int i=1;i<100;i++)
    t =i;
    while(scanf("%d",&n)&&n!=0){
    if(n==1)
    printf("Printing order for 1 pages:nSheet 1, front: Blank, 1n");
    else {
    if(n%4) p=n/4+1;
    else p=n/4;
    int q=4*p;
    printf("Printing order for %d pages:n",n);
    for(int i=0;i<p;i++){
    printf("Sheet %d, front: ",i+1);
    if(q>n) {printf("Blank, %dn",t[2*i+1]);}
    else {printf("%d, %dn",q,t[2*i+1]);}
    q–;//打印表前
    printf("Sheet %d, back : ",i+1);
    if(q>n) {printf("%d, Blankn",t[2*i+2]);}
    else {printf("%d, %dn",t[2*i+2],q);}
    q–;//打印表后
    }
    }
    }
    return 0;
    }

  2. 站长,你好!
    你创办的的网站非常好,为我们学习算法练习编程提供了一个很好的平台,我想给你提个小建议,就是要能把每道题目的难度标出来就好了,这样我们学习起来会有一个循序渐进的过程!

  3. 5.1处,反了;“上一个操作符的优先级比操作符ch的优先级大,或栈是空的就入栈。”如代码所述,应为“上一个操作符的优先级比操作符ch的优先级小,或栈是空的就入栈。”