题目大意
有N个人照相,现将N个人排成K行,每一行都有N/K个人,并按照如下规则排列
- 1、对于多出来的人全部在最后一排
- 2、前一排的人都比后一排的人矮
- 3、每一行最高的人都在中间位置
- 4、视角从下往上看(面对着看),每一行最中间的人开始,先左再右形成非递增序列
- 5、对于有相同身高的人,按照字典序升序排列
现在要求你输出该排列结果。
算法思路
有两种方法解决该问题,可以直接进行输出,不过位置的计算较为复杂并且不易阅读,这里采用模拟排列的过程来求解。我们将每一个人的姓名和身高进行绑定并且按照规定进行统一排序(高个子的在前面),然后从最后一排往前依次进行排列(输出的顺序),排列方法如下:
- 1、首先初始化当前队列temp,其容量为m
- 2、使用index记录全局队列中待排列的当前人
- 3、填充中间位置temp[m / 2] = allPeo[index++];
- 4、使用pointLeft和pointRight分别指向中间位置的左右两边邻近的位置,并使用count记录当前已经填充的人数
- 5、在count为奇数的时候填充左边,否则填充右边
- 6、每一行填充完毕后输出temp并换行。
提交结果
AC代码
#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
struct People {
string name;
int height{};
} people;
vector<People> allPeo;
bool cmp(const People &p1, const People &p2) {
return p1.height != p2.height ? p1.height > p2.height : p1.name < p2.name;
}
int main() {
int N, K;
scanf("%d %d", &N, &K);
for (int i = 0; i < N; ++i) {
cin >> people.name >> people.height;
allPeo.push_back(people);
}
sort(allPeo.begin(), allPeo.end(), cmp);
int eachRowNum = N / K;
int lastRowNum = eachRowNum + N % K;
int index = 0;
// 输出每一行的排列
for (int i = 0; i < K; ++i) {
int m = i == 0 ? lastRowNum : eachRowNum;
vector<People> temp(m);
int pointLeft = m / 2 - 1;
int pointRight = m / 2 + 1;
temp[m / 2] = allPeo[index++];
int count = 1;
while (count < m) {
if (count % 2 != 0) {
temp[pointLeft--] = allPeo[index++];
} else {
temp[pointRight++] = allPeo[index++];
}
++count;
}
for (int j = 0; j < temp.size(); ++j) {
cout << temp[j].name;
if (j < temp.size() - 1) cout << " ";
}
if (i < K - 1) {
cout << endl;
}
}
return 0;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。