1085 PAT單位排行——C++實現
題目
1085 PAT單位排行 (25 point(s))
每次 PAT 考試結束後,考試中心都會發佈一個考生單位排行榜。本題就請你實現這個功能。
輸入格式:
輸入第一行給出一個正整數 N(≤105),即考生人數。隨後 N 行,每行按下列格式給出一個考生的資訊:
准考證號 得分 學校
其中
准考證號
是由 6 個字元組成的字串,其首字母表示考試的級別:B
代表乙級,A
代表甲級,T
代表頂級;得分
是 [0, 100] 區間內的整數;學校
是由不超過 6 個英文字母組成的單位碼(大小寫無關)。注意:題目保證每個考生的准考證號是不同的。輸出格式:
首先在一行中輸出單位個數。隨後按以下格式非降序輸出單位的排行榜:
排名 學校 加權總分 考生人數
其中
排名
是該單位的排名(從 1 開始);學校
是全部按小寫字母輸出的單位碼;加權總分
定義為乙級總分/1.5 + 甲級總分 + 頂級總分*1.5
的整數部分;考生人數
是該屬於單位的考生的總人數。學校首先按加權總分排行。如有並列,則應對應相同的排名,並按考生人數升序輸出。如果仍然並列,則按單位碼的字典序輸出。
輸入樣例:
10 A57908 85 Au B57908 54 LanX A37487 60 au T28374 67 CMU T32486 24 hypu A66734 92 cmu B76378 71 AU A47780 45 lanx A72809 100 pku A03274 45 hypu
輸出樣例:
5 1 cmu 192 2 1 au 192 3 3 pku 100 1 4 hypu 81 2 4 lanx 81 2
演算法
這道題目有這樣幾個難點,首先在於採用何種資料結構進行儲存。由於map只能建立單一的key-value,因此在這道題目裡面顯得不夠用。看到別人的程式碼採用兩個map可以解決這個問題,兩個map都以學校的字串為key,一個以學生人數為value,一個以總分為value。由於這裡總分是所有的某一類計算求和之後再進行加權,因此用double就可以解決這個問題。最後輸出時在強制型別轉換即可。學校的輸入有大小寫,可以先都轉化成小寫(題目輸出要小寫),再進行map儲存。
對於排名的處理:設立pres表示前一個學校的加權總分,如果pres和當前學校的加權總分不同,說明rank等於陣列下標+1,否則rank不變~
更新後的pat系統會導致之前使用map的程式碼最後一個測試點超時,更改為unordered_map即可AC~因為無序的map沒有進行排序,會使程式執行時間變短。
程式碼
#include <iostream>
#include <vector>
#include <unordered_map>
#include <cctype>
#include <algorithm>
using namespace std;
struct node{
string id;
int score,cnt;
};
bool cmp(node a,node b){
if(a.score !=b.score ) return a.score >b.score ;
else if(a.cnt!=b.cnt ) return a.cnt <b.cnt ;
else return a.id <b.id ;
}
int main(){
double N,tmp,rank=0,pres=-1; cin>>N;
unordered_map<string,int> idx;
unordered_map<string,double> sum;
vector<node> v;
string s1,s2;
for(int i=0;i<N;i++){
cin>>s1>>tmp>>s2;
for(int j=0;j<s2.length() ;j++) s2[j]=tolower(s2[j]);//全部轉化為小寫
idx[s2]++; //計算每個學校的人數
if(s1[0]=='T') sum[s2]+=tmp*1.5;
if(s1[0]=='A') sum[s2]+=tmp;
if(s1[0]=='B') sum[s2]+=tmp/1.5;
}
for(auto it=idx.begin();it!=idx.end();it++) v.push_back(node{it->first,int(sum[it->first]),idx[it->first]});
sort(v.begin(),v.end(),cmp);
printf("%d\n",v.size());
for(int i=0;i<v.size();i++){
if(pres!=v[i].score) rank=i+1;
pres=v[i].score;
cout<<rank<<" ";
cout<<v[i].id;
cout<<" "<<v[i].score<<" "<<v[i].cnt<<endl;
}
return 0;
}