日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CSP201912-3化学方程式

發(fā)布時間:2024/1/8 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CSP201912-3化学方程式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.



思路分析
每輸入一個方程式即處理一個方程式,這樣可以減少存儲開銷。對輸入的方程式,將其進(jìn)行多次切分,首先以“=”為界限,將方程式切分為左半部分和右半部分。此操作在主函數(shù)中進(jìn)行。再對這兩部分,以“+”為界限分別進(jìn)行切割,此時切割出來的稱為基本項。此操作在如下函數(shù)中進(jìn)行。

void ProcessExpr(string expr,char side)

對每一個基本項進(jìn)行處理,首先提取出基本項的系數(shù),比如說4Na(Au(CN)2)的系數(shù)是4,Na(OH)2的系數(shù)是1,。將系數(shù)分離出來之后,得到的就是化學(xué)式,上面給出的兩個基本項提取系數(shù)后得到的化學(xué)式分別為Na(Au(CN)2)和NA(OH)2。再遍歷化學(xué)式的每一個字符,分為如下幾種情況。
若當(dāng)前遍歷到的字符是大寫字母,則判斷下一個字符是否為小寫字母,從而得到原子式。之后再提取該原子的下標(biāo)。
若當(dāng)前遍歷到的字符是’(’,則進(jìn)入遞歸處理函數(shù)。遞歸的操作是若遇到’)‘則結(jié)束當(dāng)前函數(shù),若遇到’('則繼續(xù)進(jìn)行遞歸,遇到大寫字母則提取其原子式。
本程序的關(guān)鍵就是對括號情況的處理,把括號問題解決之后,其余的就都是一些細(xì)節(jié)問題了。

#include <iostream> #include<string> #include<vector> #include<stack> #include<map> #include<algorithm> using namespace std; map<string, int> ma1, ma2;//分別存儲方程式的左邊和右邊的原子 //分離出系數(shù)來并存放在coef中 void GetCoef(string formula,int & coef,int & index) {string temp = formula.substr(index);size_t indx = 0;try {coef = stoi(temp, &indx, 10);index += indx;}catch (exception e) { coef = 1; } } //處理括號的情況 void ProcessBra(string formula,map<string,int> & bracketMap,int & index) {while (true) {string atom = string(1, formula[index]);index++;if (atom == "(") {map<string, int> inBra;//存放括號里的原子ProcessBra(formula, inBra,index);int num;//括號的下標(biāo)GetCoef(formula, num, index);for (auto i = inBra.begin(); i != inBra.end(); i++) {//將內(nèi)層括號中的原子乘以括號的下標(biāo)之后加到bracketMap中bracketMap[(*i).first] += (*i).second * num;}}else if (atom == ")") {return;}else {if (formula[index] >= 'a' && formula[index] <= 'z') {atom += string(1, formula[index]); index++;}int subscript;//緊跟原子的下標(biāo)GetCoef(formula, subscript, index);bracketMap[atom] += subscript;}} } //處理方程式的每一項 void ProcessFormula(string coefFormula,char side) {int coef = 1;//系數(shù)int index = 0;//處理當(dāng)前項時的索引GetCoef(coefFormula, coef, index);string formula = coefFormula.substr(index);index = 0;map<string, int> tempMap;//存放當(dāng)前項的原子string atom;while (index < formula.size()) {atom = formula.substr(index, 1);index++;if (atom == "(") {map<string, int> inBra;ProcessBra(formula,inBra, index);int num;//求括號的下標(biāo)GetCoef(formula, num, index);for (auto i = inBra.begin(); i != inBra.end(); i++) {//將括號中的原子乘以括號的下標(biāo)之后加到tempMap中tempMap[(*i).first] += (*i).second * num;}}else {if (formula[index] >= 'a' && formula[index] <= 'z') {//判斷緊鄰的下一個字符是否為小寫字母atom += formula[index];index++;}int num;GetCoef(formula, num, index);tempMap[atom] += num;}}for (auto i = tempMap.begin(); i != tempMap.end(); i++) {if(side =='l')//如果是方程式的左側(cè),則更新ma1,否則更新ma2ma1[(*i).first] += (*i).second *coef;elsema2[(*i).first] += (*i).second *coef;} } //將方程式的每一項拆分開 void ProcessExpr(string expr,char side) {int start = 0, end;//充當(dāng)切分方程時的索引值string coefFormula;//系數(shù)和分子式while (true) {end = expr.find('+', start);if (end == -1) {//只剩下最后一項coefFormula = expr.substr(start);ProcessFormula(coefFormula, side);break;}coefFormula = expr.substr(start, end - start);ProcessFormula(coefFormula,side);start = end + 1;} } int main() {int n;string equation;//輸入的方程式string left, right;//將方程式以‘=’為界限,分為左半部分和右半部分cin >> n;for (int i = 0; i < n; i++) {ma1.clear(), ma2.clear();cin >> equation;int position = equation.find('=', 0);left = equation.substr(0, position);right = equation.substr(position+1);ProcessExpr(left, 'l');ProcessExpr(right, 'r');if (ma1 != ma2)puts("N");elseputs("Y");} }

上面給出的源碼在CCF系統(tǒng)中經(jīng)過測試是一百分,但這并不是我最初的代碼。剛開始時我是用的結(jié)構(gòu)體存儲的原子,對括號的處理也沒有采用遞歸,而是采用了一種棧的思想。比如說化學(xué)式Na(Au2(O(CN3)2S)3,在對其每個字符進(jìn)行遍歷時,當(dāng)遍歷到’(’,則把它的位置入棧,遍歷到’)’,則彈出棧頂元素,因為沒分離出一個原子,就把它順序的存儲到結(jié)構(gòu)體數(shù)組中,因此這樣就可以定位到括號內(nèi)的原子。之后再提取括號的下標(biāo),讓括號內(nèi)的每個原子的原子數(shù)都乘以下標(biāo)。當(dāng)時按照這種方法寫出的程序卻之后90分,找了好長時間也沒發(fā)現(xiàn)問題在那兒,下面給出源碼,還望大神指正。

#include <iostream> #include<string> #include<vector> #include<stack> #include<algorithm> using namespace std; struct Atom {string name;int amount; }; Atom atomL[1000],atomR[1000];//方程左側(cè)的原子和右側(cè)的原子 int countL = 0, countR = 0;//方程式左邊的元素種類數(shù)和右邊的元素種類數(shù) void AddToLeft(Atom a) {int i;for ( i = 0; i < countL; i++) {if (a.name == atomL[i].name) {atomL[i].amount += a.amount;break;}}if (i == countL) {atomL[i].name = a.name;atomL[i].amount = a.amount;countL++;} } void AddToRight(Atom a) {int i;for (i = 0; i < countR; i++) {if (a.name == atomR[i].name) {atomR[i].amount += a.amount;break;}}if (i == countR) {atomR[i].name = a.name;atomR[i].amount = a.amount;countR++;} } //處理方程式的每一項 void ProcessFormula(string coefFormula,char side) {size_t indx = 0;//字符串進(jìn)行數(shù)值轉(zhuǎn)換時,存放轉(zhuǎn)換過程中第一個不被接受的字符的索引int coef = 1;//系數(shù)string formula;//分子式try {coef = stoi(coefFormula,&indx,10);}catch (exception e){}formula = coefFormula.substr(indx);vector<Atom> formulaAtom;//當(dāng)前分子式所含的原子stack<int> bracket;//存放左括號的位置int index = 0;//處理分子式時的索引int count = 0;//記錄有多少種原子string atom;while (index < formula.size()) {atom = formula.substr(index, 1);index++;if (atom == "(") {bracket.push(count);}else if (atom == ")") {string temp = formula.substr(index);int num = 1;try {num = stoi(temp, &indx, 10);index += indx;}catch (exception e) {}if (num != 1) {for (int i = bracket.top(); i < count; i++) {formulaAtom[i].amount *= num;}bracket.pop();}}else {string str;str = formula.substr(index, 1);if (str[0] >= 'a'&&str[0] <= 'z') {//判斷緊鄰的下一個字符是否為小寫字母atom += str;index++;}string temp = formula.substr(index);int num = 1;try {num = stoi(temp, &indx, 10);index += indx;}catch (exception e) {}Atom tempAtom = { atom,num };formulaAtom.push_back(tempAtom);count++;}}for (int i = 0; i < count; i++) {formulaAtom[i].amount *= coef;if (side == 'l')AddToLeft(formulaAtom[i]);elseAddToRight(formulaAtom[i]);} } //將方程式的每一項拆分開 void ProcessExpr(string expr,char side) {int start = 0, end;//充當(dāng)切分方程時的索引值string coefFormula;//系數(shù)和分子式while (true) {end = expr.find('+', start);if (end == -1) {//只剩下最后一項coefFormula = expr.substr(start);ProcessFormula(coefFormula, side);break;}coefFormula = expr.substr(start, end - start);ProcessFormula(coefFormula,side);start = end + 1;} } bool compare(Atom a1, Atom a2) {if (a1.name < a2.name)return true;else return false; } //判斷方程是否配平 bool Judge() {if (countL == countR) { sort(atomL, atomL + countL,compare);sort(atomR, atomR + countR,compare);for (int i = 0; i < countL; i++) {if (atomL[i].name != atomR[i].name || atomL[i].amount != atomR[i].amount)return false;}return true;}elsereturn false; } int main() {int n;cin >> n;char result[100];//存放最后的判斷結(jié)果for (int i = 0; i < n; i++) {countL = countR = 0;string equation;cin >> equation;string left, right;//將方程式以‘=’為界限,分為左半部分和右半部分int position = equation.find('=', 0);left = equation.substr(0, position);right = equation.substr(position+1);ProcessExpr(left, 'l');ProcessExpr(right, 'r');if (Judge())result[i] = 'Y';elseresult[i] = 'N';}for (int i = 0; i < n; i++)cout << result[i] << endl; }

附測試用例

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

總結(jié)

以上是生活随笔為你收集整理的CSP201912-3化学方程式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。