奥利给!先放个题目链接
201912-3化学方程式
思路和感悟:
这题真是去年参加CSP的败笔!明明已经做对了几个测试点,最后却提交了个全错的,把对的顶走了!!!每每想起,都想打自己一顿!算了,怎么能打自己呢!砸键盘吧!
今天又做了一遍,做了9个测试的的内容,但是不知道咋回事,加入数字那一块的测试点就是过不了OTZ,只得了40分······想用STL,尤其是stringstream,无奈学识实在浅薄,用不好,只会空格分割和格式转换。
然后我就参考了一位大佬的代码,真的是太妙了TAT
总结一下
#include <sstream>
using namespace std;
int main(){
string str="4Au+8NaCN+2H2O+O2=4Na(Au(CN)2)+4NaOH";
stringstream ss(str);
string lstr,rstr;
getline(ss,lstr,'=');
cout<<lstr<<endl//4Au+8NaCN+2H2O+O2
getline(ss,rstr);
cout<<rstr<<endl;//4Na(Au(CN)2)+4NaOH
string item;
while(getline(rstr,item,'+'){
cout<<item<<endl;//4Au//8NaCN//2H2O//O2
}
return 0;
}
/***********************************************************/
#include <cctype>
using namespace std;
int main(){
char c1='a';
char c2='A';
char c3='1';
if(islower(c1))//判断是否小写字母
cout<<c1<<endl;//a
if(isupper(c2))//判断是否大写字母
cout<<c2<<endl;//A
if(isdigit(c3))//判断是否数字
cout<<c3<<endl;//1
}
/***********************************************************/
vector向量作为常用的容器之一,某些时候很好用,
比如邻接表,有时也能代替栈和队列使用,
多做题、多总结、多学习。
测试样例
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
完整代码(100分)
#include<cctype>
#include<iostream>
#include<string>
#include<sstream>
#include<map>
#include<vector>
using namespace std;
struct Elem{
string name;
int num;
Elem(string _name,int _num):name(_name),num(_num){}
};
int toNumber(string str,int &pos){//得到系数,如2,12,123
int num=0;
while(isdigit(str[pos])){
num=num*10+str[pos]-'0';
pos++;
}
return num;
}
void calc(string &str,map<string,int> &mp){//对式子两边表达式分别进行元素的统计
stringstream ss(str);
string item;
while(getline(ss,item,'+')){//对每个化学式进行更细化的分析,如4Na(Au(CN)2)
vector<Elem> arr;
int factor=1;//初始化化学式的系数为1
int i=0;
if(isdigit(item[i]))//如果由系数
factor=toNumber(item,i);
while(i<item.size()){//往后继续分析
if(isupper(item[i])){//当前字符为大写字母
string name;
name+=item[i++];
if(islower(item[i])){//如果下一位是小写字母,则是Cu这一类的元素
name+=item[i++];
}//否则就是H这种单字符元素
arr.push_back(Elem(name,1));//初始数量为1
}
else if(item[i]=='('){//当前字符为左括号
arr.push_back(Elem("(",0));
i++;
}
else if(item[i]==')'){//当前字符为右括号
arr.push_back(Elem(")",0));
if(!isdigit(item[++i]))
item.insert(i,"1");//如果()后无系数,则插入个1,
//这样每经过一个')'都会开始检查数字字符
}
else if(isdigit(item[i])){//*当前字符为数字,处理嵌套的核心代码
int num=toNumber(item,i);
if(arr[arr.size()-1].name==")"){//看看这个系数是单个元素的系数,
//还是一个根的系数,如(OH)2,这里是判断根
//注,该系数未插入到arr里
int j=arr.size()-1;
arr[j].name="*";//访问过,标记为*
while(arr[--j].name!="("){//遇到第一个name为'('的Elem
arr[j].num*=num;//过程中的每个Elem的数量都乘系数
}
arr[j].name="*";//标记
}
else{
arr[arr.size()-1].num*=num;//是单个元素的系数
}
}
}
for(i=0;i<arr.size();i++){//统计入map里
if(arr[i].name=="*")
continue;
mp[arr[i].name]+=arr[i].num*factor;
}
}
}
bool judge(map<string ,int> &lmp,map<string ,int> &rmp){//判断是否合法
if(lmp.size()!=rmp.size())//不加的话,最后一个测试点过不了
return false;
for(map<string ,int>::iterator it=lmp.begin();it!=lmp.end();it++)
if(it->second!=rmp[it->first])
return false;
return true;
}
int main(){
int n;
cin>>n;
while(n--){
string str,lstr,rstr;
cin>>str;
stringstream ss(str);
map<string ,int> lmp,rmp;
getline(ss,lstr,'=');//cut
getline(ss,rstr);
calc(lstr,lmp);//run
calc(rstr,rmp);
if(judge(lmp,rmp))//result
cout<<"Y"<<endl;
else
cout<<"N"<<endl;
}
}