Dark模擬的第一次嘗試
【解題報告】 P4711 「化學」相對分子質量
雖然作為一道模擬題,但是畢竟是本人打出的第一道名副其實的模擬題,所以我在這裡覺得有必要寫一個部落格來紀念一下。順便總結一下一些模擬題的做法。
題目傳送門:P4711 「化學」相對分子質量
但是我看到這道題的時候也是一臉懵逼,因為我想到這個化學式可能是括號套括號,所以當時因為這個問題我思考了好久,但是後來發現其實這根本是沒有必要的,因為原子團中的括號只可能有一個,不可能套一堆上去,所以說當我們明白了這一點的時候,我們就又離成功近了一步,於是我們只需要整理一下思路進行下面的處理就可以了。
1、首先我們發現的是化學式中有很多的數字資訊等待我們去處理,所以說我們有必要寫一個讀入數字的程式,那麼其實這個東西也是非常好寫的,我們只需要往函式中讀入第一個數字所在的位置,然後往後進行數,看下一位是不是數字,依次類推,直到不是數字我們就彈出迴圈,然後就可以了。這裡不要忘了,我們傳入當前化學式第i個位置尋找數字,那麼尋找完畢後我們也應該同步更改化學式i的值,往後加。
2、其次我們也發現化學式中有很多元素,所以我們也要對他進行處理,我們書寫一個函式,當每次在主程式中找到一個大寫字母后,進入函式,確定他的元素名稱,並且利用上面第一個找數字的函式找到這個元素有幾個,然後我們就可以算出這個元素的質量,然後用此函式進行返回就可以了。
3、最後,讓我們來解決一下最難的一個問題,就是當化學式中出現了原子團我們應該如何應對。應對方法如下:
當我們找到一個“(”時表明我們找到了一個原子團,這個時候我們在主程式中巢狀一個找到“)”才停止的迴圈,再開一個臨時的變數用於存放當前一個原子團的相對分子質量然後我們利用上面一樣的思想,每當找到一個大寫字母,我們就加上當前元素的相對原子質量,然後當我們碰到了“)”時,說明我們已經累加完了單個原子團的相對原子質量,然後我們判斷一下後面有沒有“——”東西,有的話,我們在呼叫找數字的函式,找出有幾個原子團然後,把他累加到總質量上,就可以了。
總而言之,我們如果想要打好模擬題,我們就要相辦法把一個困難的問題分成很多很小且簡單的問題,這樣就可以了!
這道題雖然難度標號非常的高,但是如果我們能夠把複雜的問題簡單化,其實還是非常的簡單的。
下面上一篇AC程式碼:
#include<bits/stdc++.h> using namespace std; map<string,double> ele; char ch[1003],b[15]; void element() { ele["H"]=1; ele["C"]=12; ele["N"]=14; ele["O"]=16; ele["F"]=19; ele["Na"]=23; ele["Mg"]=24; ele["Al"]=27; ele["Si"]=28; ele["P"]=31; ele["S"]=32; ele["Cl"]=35.5; ele["K"]=39; ele["Ca"]=40; ele["Mn"]=55; ele["Fe"]=56; ele["Cu"]=64; ele["Zn"]=65; ele["Ag"]=108; ele["I"]=127; ele["Ba"]=137; ele["Hf"]=178.5; ele["Pt"]=195; ele["Au"]=197; ele["Hg"]=201; } int number(int &i) { int x=0; while(ch[i]>='0'&&ch[i]<='9') { x=x*10+(ch[i]-'0'); i++; } i--; return x; } double name(int &i) { bool flag=false; memset(b,0,sizeof(b)); int cnt=-1; while(((ch[i]>='A'&&ch[i]<='Z')||(ch[i]>='a'&&ch[i]<='z'))&&(cnt<0||(cnt>=0&&(ch[i]>='a'&&ch[i]<='z')))) { flag=true; cnt++; b[cnt]=ch[i]; i++; } if(ch[i]=='_') { i=i+2; int count=number(i); return count*ele[b]; } else { if(flag) i--; return ele[b]; } } int main() { double s,k;s=0; element(); cin.getline(ch,1003); int sk=strlen(ch); for(int i=0;i<sk;++i) { if(ch[i]>='A'&&ch[i]<='Z') s+=name(i); if(ch[i]=='(') { double sum; sum=0; i++; for(k=0;ch[i]!=')';i++) k+=name(i); if(ch[i+1]=='_') i=i+3; s+=k*number(i); } if(ch[i]=='~') { i++; if(ch[i]=='H') s+=18.0; else { s+=number(i)*18.0; } break; } } printf("%g",s); return 0; }
謝謝採納!