拍集體照時隊形很重要,這裏對給定的N個人K排的隊形設計排隊規則如下:
- 每排人數爲N/K(向下取整),多出來的人全部站在最後一排;
- 後排所有人的個子都不比前排任何人矮;
- 每排中最高者站中間(中間位置爲m/2+1,其中m爲該排人數,除法向下取整);
- 每排其他人以中間人爲軸,按身高非增序,先右後左交替入隊站在中間人的兩側(例如5人身高爲190、188、186、175、170,則隊形爲175、188、190、186、170。這裏假設你面對拍照者,所以你的左邊是中間人的右邊);
- 若多人身高相同,則按名字的字典序升序排列。這裏保證無重名。
現給定一組拍照人,請編寫程序輸出他們的隊形。
輸入格式:
每個輸入包含1個測試用例。每個測試用例第1行給出兩個正整數N(<=10000,總人數)和K(<=10,總排數)。隨後N行,每行給出一個人的名字(不包含空格、長度不超過8個英文字母)和身高([30, 300]區間內的整數)。
輸出格式:
輸出拍照的隊形。即K排人名,其間以空格分隔,行末不得有多餘空格。注意:假設你面對拍照者,後排的人輸出在上方,前排輸出在下方。
輸入樣例:10 3
Tom 188
Mike 170
Eva 168
Tim 160
Joe 190
Ann 168
Bob 175
Nick 186
Amy 160
John 159
輸出樣例:Bob Tom Joe Nick
Ann Mike Eva
Tim Amy John
==========================================================================
思路:
事比較多,注意別考慮漏了。
這裏先使用結構體和自寫cmp完成題目要求的一維排序,然後再從頭到尾安排到隊形里正確的位置上。
由於最後一排可能會多出人所以先排最後一排。但每排的思路是一樣的,先把最高的扔該排中間,然後以該人爲中心左右反覆
排,直到該排人數已滿。利用 j *= -1 完成左右反覆排位的需求。
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <sstream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
struct student
{
string name;
int hight;
};
bool cmp(student x, student y)
{
if(x.hight == y.hight)
return x.name < y.name;
else
return x.hight > y.hight;
}
int main()
{
int n,k,m,l,i,j,q,temp,cnt=0;
student stu[10005];
cin>>n>>k;
m = n/k;
l = m + n%k;
string formation[k][l];
for(i=0;i<n;i++)
cin>>stu[i].name>>stu[i].hight;
sort(stu,stu+n,cmp);
j = 0;
for(i=0;i<l;i++)
{
j *= -1;
formation[0][l/2 + j] = stu[cnt++].name;
if(i%2 == 0)
j++;
}
for(q=1;q<k;q++)
{
j = 0;
for(i=0;i<m;i++)
{
j *= -1;
formation[q][m/2 + j] = stu[cnt++].name;
if(i%2 == 0)
j++;
}
}
for(j=0;j<l;j++)
{
cout<<formation[0][j];
if(j < l-1)
cout<<" ";
}
if(k > 1)
cout<<endl;
for(i=1;i<k;i++)
{
for(j=0;j<m;j++)
{
cout<<formation[i][j];
if(j < m-1)
cout<<" ";
}
if(i < k-1)
cout<<endl;
}
return 0;
}