pat 甲級 1080(模擬題)
阿新 • • 發佈:2018-11-18
題目連結:https://pintia.cn/problem-sets/994805342720868352/problems/994805387268571136
思路:
1、題目大意是,模擬高考錄取學生的過程,每個學生有三種成績
(1)GE錄取成績(2)GI面試成績(3)最終成績GF=(GE+GI)/2;
按學生的排名有以下規則:
(1)學生的最終成績從大到小排列
(2)學生的最終成績相同的情況下,需要比較學生的面試成績,從高到低,如果學生的面試成績也相同,
那麼他們擁有相同的排名。
錄取規則:
(1)每個考生擁有k個志願,優先考慮前面的志願。
(2)每個學校有mi個錄取名額,如果學生排名相同且超過錄取名額,依然錄取。
輸入:
第一行,n,m,k表示學生人數,學校數目,每個考生可以報考的學校的數目。
第二行,m個表示每個學校最多錄取的學生人數
之後,n行每個學生的資訊
學生的GE,GI,然後k個學生想要報考的學校。
輸出
每行,每行表示每個學校可以錄取的學生的編號。如果某個學校沒人報,就輸出空行
思路:
1、學生的排名從小到大
2、每次學校錄取可以錄取的學生,如果學校的錄取名額滿了,並且將要錄取的學生的排名和學校最後一名的
排名相同,依舊錄取。(這裡不用提前將學生的排名記錄,直接比較GE和GF相同就行了)
3、注意當比較最後一個學生是一定是排序後的編號,但vc中儲存的是原編號,所以要提前用mp記錄一下。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<map> using namespace std; const int maxn = 40040; struct Node{ int GI,GE,GF,id,rk; int cho[10]; }; Node nd[maxn]; map <int,int> mp; vector <int> vc[120]; int sch[120],m,n,k,vis[maxn]; bool cmp(Node a,Node b) { if(a.GF!=b.GF) return a.GF>b.GF; else return a.GE>b.GE; } int main(void) { int i,j,p; scanf("%d%d%d",&n,&m,&k); memset(vis,0,sizeof(vis)); for(i=0;i<m;i++) scanf("%d",&sch[i]); for(i=0;i<n;i++) { scanf("%d%d",&nd[i].GE,&nd[i].GI); nd[i].id=i; nd[i].GF=(nd[i].GE+nd[i].GI)/2; for(j=0;j<k;j++) scanf("%d",&nd[i].cho[j]); } sort(nd,nd+n,cmp); for(i=0;i<n;i++) mp[nd[i].id]=i; //記錄排序後的編號 for(i=0;i<n;i++) { for(j=0;j<k;j++) { if(sch[nd[i].cho[j]]>0) { vc[nd[i].cho[j]].push_back(nd[i].id); sch[nd[i].cho[j]]--; break; } else if(sch[nd[i].cho[j]]==0) { p=vc[nd[i].cho[j]].size(); int tp=mp[vc[nd[i].cho[j]][p-1]]; //是排序後的編號 if(nd[tp].GF==nd[i].GF&&nd[tp].GE==nd[i].GE) { vc[nd[i].cho[j]].push_back(nd[i].id);break; //這裡斷開 } } } } for(i=0;i<m;i++) { if(vc[i].size()==0) { printf("\n"); continue; } sort(vc[i].begin(),vc[i].end()); for(j=0;j<vc[i].size()-1;j++) printf("%d ",vc[i][j]); printf("%d\n",vc[i][j]); } return 0; }