CCF-CSP題解 201912-3化學方程式【字符串處理+模擬】

奧利給!先放個題目鏈接

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;

    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章