PTA 1055 集體照
拍集體照時隊形很重要,這裡對給定的N個人K排的隊形設計排隊規則如下:
每排人數為/(向下取整),多出來的人全部站在最後一排;
後排所有人的個子都不比前排任何人矮;
每排中最高者站中間(中間位置為/,其中m為該排人數,除法向下取整);
每排其他人以中間人為軸,按身高非增序,先右後左交替入隊站在中間人的兩側(例如5人身高為190、188、186、175、170,則隊形為175、188、190、186、170。這裡假設你面對拍照者,所以你的左邊是中間人的右邊);
若多人身高相同,則按名字的字典序升序排列。這裡保證無重名。
現給定一組拍照人,請編寫程式輸出他們的隊形。
輸入格式:
每個輸入包含 1 個測試用例。每個測試用例第 1 行給出兩個正整數N(≤,總人數)和K(≤,總排數)。隨後N行,每行給出一個人的名字(不包含空格、長度不超過 8 個英文字母)和身高([30, 300] 區間內的整數)。
輸出格式:
輸出拍照的隊形。即K排人名,其間以空格分隔,行末不得有多餘空格。注意:假設你面對拍照者,後排的人輸出在上方,前排輸出在下方.
輸入
Bob Tom Joe Nick Ann Mike Eva Tim Amy John
輸出
10 3 Tom 188 Mike 170 Eva 168 Tim 160 Joe 190 Ann 168 Bob 175 Nick 186 Amy 160 John 159
從簡單開始想起:
首先排序。我這裡是從小到大排。
由題目可以知道除了最後一排的每排人數為rs=N/K, 最後一排的個數為lastrs=N/K+N%(N/K)
這意味著 最後一排的物件在陣列中的位置為 N-lastrs+1~N,
倒數第二排的物件在陣列中的位置為N-lastrs+1-rs~N-lastrs
倒數第n排的物件在陣列中的位置為 N-lastrs+1-rs*(n-1)~N-lastrs-rs*(n-2)
現在我們已經得到了每行的資料都是啥,接下來就是給每行資料進行重排。
為了將題目簡化,我們可以理解為對於某一行物件從l到r的重排, 物件個數為len=r-l+1
當len為奇數的時候:
黑色筆跡的是題意的思路。從大到小插入,然後輸出, 但是這樣很不方便。
紅色和藍色筆跡是另一種思路。把每一次插入都計數num。當是奇數的時候往藍色部分插入,當是偶數的時候往紅色部分插入。輸出的時候紅色部分直接按照插入的順序輸出,藍色部分需要倒序輸出。
因此我們可以在num為偶數的時候讀到紅色部分就直接輸出,num為奇數的時候存到一個棧裡面,資料讀完後彈出所有的內容。
當len為偶數時:
思路同上。但是紅色部分變為當num為奇數,藍色部分變為num為偶數。
程式碼
1 #include<iostream> 2 #include<cstring> 3 #include<fstream> 4 #include<algorithm> 5 #include<stack> 6 using namespace std; 7 typedef long long ll; 8 const ll mx=1e4+10; 9 typedef struct node{ 10 string name; 11 ll sg; 12 }STU; 13 STU stu[mx]; 14 bool cmp(const STU&a, const STU&b){ 15 if(a.sg==b.sg) return a.name>b.name; 16 return a.sg<b.sg; 17 } 18 void paidui(ll l, ll r){ 19 stack<string>q; 20 ll num=0, base=(r-l+1)%2==0?1:0;//len 偶數base為1 21 bool appe=false; 22 for(ll i=l;i<=r;i++){ 23 num++; 24 if(num%2==base){//紅色部分 直接輸出 25 if(appe) cout<<" "; 26 appe=true; 27 cout<<stu[i].name; 28 } 29 else{ 30 q.push(stu[i].name); 31 } 32 } 33 while(!q.empty()){//藍色部分 棧彈出使其倒序輸出 34 if(appe) cout<<" "; 35 cout<<q.top(); 36 q.pop(); 37 } 38 cout<<endl; 39 } 40 int main(){ 41 ll N, K; 42 cin>>N>>K; 43 for(ll i=1;i<=N;i++){ 44 cin>>stu[i].name>>stu[i].sg; 45 } 46 sort(stu+1, stu+N+1, cmp); 47 48 ll rs=N/K, lastrs=rs+N%rs; 49 //第一行 最後一排 50 ll d=N-lastrs+1; 51 paidui(d, N); 52 53 //其他幾行 54 for(ll i=1;i<=K-1;i++){ 55 paidui(d-rs*i, d-1-rs*(i-1)); 56 } 57 58 return 0; 59 }