思路分析:
这道题乍一看挺麻烦的,其实则不然。本题主要难点是以下两步:
1.首先需要将所有人按给定的排序规则存储到容器中,这就需要用到容器的自定义排序。
2.”每排其他人以中间人为轴,按身高非增序,先右后左交替入队站在中间人的两侧” 这句话看似很复杂,其实只需要用双端队列就可以解决,当然也可以找到数字之间的规律。
具体步骤:
- 声明结构体或类,取名为Person,内部维护name、height两个成员变量,权限为public;
- 自定义排序规则MySort,按照题目指定规则排序;
- 在主函数中读取待排队人员并进行排列供后面使用;
- 判断能否正好排成矩阵,并记录最多排成矩阵的列数为k2;
- 执行k2次循环,每个循环内选中一排进行双端交替入队,用一个标记位判断是从队头进还是队尾进,当一排全部入队之后,将整一排信息入栈;
- 如果不能排成矩阵,说明还有剩余的人,而且一定是高个。与步骤5同样的道理排队并入栈;
- 依次将栈中元素出栈,就得到了所求结果。
示例代码:
#include<iostream>
#include<vector>
#include<string>
#include<deque>
#include<stack>
#include<algorithm>
using namespace std;
class Person {
public:
string name;
int height;
};
struct MySort{
public:
bool operator()(const Person& p1, const Person p2){
if(p1.height < p2.height){
return true;
}else if(p1.height == p2.height && p1.name > p2.name){
return true;
}
return false;
}
};
int main(){
int n,k; cin >> n >> k;
vector<Person> vec;
for(int i = 0; i < n; i++){
string str;int wei;
cin>>str>>wei;
Person p;
p.name = str;
p.height = wei;
vec.push_back(p);
}
sort(vec.begin(),vec.end(),MySort());//把人员升序排列
stack<deque<Person>> sta;//存储所有排队讯息
int num = n/k;//向下取整 每队队列人数
int k2 = k;
if(num * k != n){//不能排成k队
k2 = k-1;
}
int point = 0;//记录每一排的起始角标
for(int i = 0; i < k2; i++){//执行k2次 保证不会溢出
bool front = false;//判断当前是进队头还是队尾
deque<Person> de;//用来存储每一队的信息
for(int j = point+num-1; j >= point; j--){//执行k2次,总共选中一队的人
if(front){
de.push_front(vec[j]);
front = false;
}else{
de.push_back(vec[j]);
front = true;
}
}
sta.push(de);
point += num;//移到下一排的队头
}
if(k2 != k){//说明还有余下的高个
deque<Person> de;//用来存储每一队的信息
bool front = false;
for(int i = vec.size() - 1; i >= point; i--){
if(front){
de.push_front(vec[i]);
front = false;
}else{
de.push_back(vec[i]);
front = true;
}
}
sta.push(de);
}
while(!sta.empty()){//将栈中的队列逆序输出
deque<Person> de = sta.top();
for(deque<Person>::iterator it = de.begin(); it != de.end()-1; it++){
cout << (*it).name <<" ";
}
cout<<(*(de.end()-1)).name<<endl;
sta.pop();
}
system("pause");
return 0;
}