1

题目大意

有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并换行。

提交结果

image.png

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;
}

乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得