CCF 2019-12-3 化学方程式(100分, 15ms)
把等号左右运算结果分别存入两个map, 比较map是否一样
括号求解是用DFS做的。
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef long long ll;
#define MAXN 1005
#define InA(a) a>='A'&&a<='Z'
#define Ina(a) a>='a'&&a<='z'
#define In0(a) a>='0'&&a<='9'
map<string, int> mp[2];
string s;
int quan, mpid;
int to_num(int l, int r){
int ans=0;
for(;l<r;l++){
ans=(ans*10 + s[l]-'0');
}
return ans;
}
int getNum(int start){
while(In0(s[start]))
start++;
return start;
}
void dealP(int &ptr){
quan=1;
ptr++;
if( In0(s[ptr] ) ) {//find num after "+"
int r = getNum(ptr);
quan = to_num(ptr, r);
ptr = r;
}
}
void dealA(int &ptr){
string ss;
ss+=s[ptr];
ptr++;
int num=1;
if(Ina(s[ptr])){// if followed by a
ss+=s[ptr];
ptr++;
}
if(In0(s[ptr])){// if followed by num
int r = getNum(ptr);
num = to_num(ptr, r);
ptr = r;
}
mp[mpid][ss]+=(num*quan);
}
int findrk(int l){// find brackets ')'
int tt=1;
while(tt){
l++;
if(s[l]=='(') tt++;
if(s[l]==')') tt--;
}
return l;
}
void DFS(int &l, int r, int val){//[l,r]
l++;
quan*=val;
while(l<r){
char c = s[l];
if(InA(c)) dealA(l);
else if(c=='('){
int rr = findrk(l);
int vall = 1;
if(In0(s[rr+1])) vall = to_num(rr+1, getNum(rr+1));
DFS(l, rr, vall);
l = getNum(rr+1);
}
}
quan/=val;
}
void dealK(int&ptr){
int ri=1;
ri = findrk(ptr);
int valu = 1;
if(In0(s[ri+1])) {
valu = to_num(ri+1, getNum(ri+1));
}
DFS(ptr, ri, valu);
ptr++;
ptr = getNum(ptr);
}
int main(){
ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
int i,j,k,n,l=0,r=0,ptr;
cin>>n;
while(n--){
cin>>s;
ptr=0;//set ptr
s.insert(0,"+");
int lend = s.find('=');
s.insert(lend+1,"+");
mpid=0; //set map
mp[0].clear(); mp[1].clear();
int len = s.size();
while(ptr<len){//main loop for one expression
char c = s[ptr];
if(c == '+') dealP(ptr);//+
else if(InA(c)) dealA(ptr);//A
else if(c == '='){//=
mpid = 1;//change map id
ptr++;
}else{//(
dealK(ptr);
}
}
if(mp[0] == mp[1])
cout<<"Y"<<endl;
else
cout<<"N"<<endl;
}
return 0;
}