PAT甲级真题1109 合影(很好的模拟题)

合影时队形非常重要,给出 NN 个人排成 KK 行的规则,如下所示:

每行的人数必须为 N/KN/K(向下取整),所有多余的人(如果有)都放到最后一行;
位于后排的所有人都不得矮于位于前排的任何人;
在每一行中,最高的人站在该行的中心位置(定义为位置 (m/2+1)(m/2+1),位置从1开始编号,其中 mm 是该行的总人数,除法结果向下取整);
在每一行中,其他人必须按照其身高非递增顺序依次排入该行,交替地将他们的位置先安排到最高人的右侧,然后再安排到最高人的左侧(例如,假设五个人的身高为 190、188,186、175、170190、188,186、175、170,最终阵型将是 175、188、190、186、170175、188、190、186、170。在这里,我们假设你面对着合影人员,因此你的左手边位置其实是最高人的右手边位置。);
当许多人的身高相同时,必须按姓名的字典序升序进行排序,保证所有人的姓名不重复。
现在,给定一群人的相关信息,请你将他们的合照队形排好。

输入格式
第一行包含两个整数,NN 表示总人数,KK 表示排成的行数。

接下来 NN 行,每行包含一个人的姓名和身高。

姓名是长度不超过 88 的由大小写字母构成的字符串,身高是范围在 [30,300][30,300] 的整数。

输出格式
输出排好的合影队形,即在 KK 行输出人员姓名。

名字之间用空格隔开,行尾不得由多余空格。

注意,由于你面对着合影人员,因此,后排的人在上方输出,前排的人在下方输出。

数据范围
1≤N≤1041≤N≤104,
1≤K≤101≤K≤10
输入样例:
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

#include<bits/stdc++.h>
using namespace std;
const int N=10010;
struct node{
	string id;
	int h;
	bool operator<(const node&a)const{
	   if(h!=a.h)return h>a.h;
	   else return id<a.id;
	}
}p[N];
int main(){
	int n,k;
	cin>>n>>k;
	for(int i=0;i<n;i++)cin>>p[i].id>>p[i].h;
	sort(p,p+n);
	int t=0;//指向p的下标 
	for(int v=0;v<k;v++){//输出多少行 
		int len=n/k;
		if(v==0)len+=n%k;//第一行人数特判 
		vector<string>s(len+1);//每一行的人数已经固定,不用存着最后一起输出,存一行输出一行 
		s[len/2+1]=p[t].id;
		int j=len/2+2;
		for(int r=t+2;r<len+t;r+=2){//注意是小于
			s[j++]=p[r].id;
		}
		j=len/2;
		for(int l=t+1;l<len+t;l+=2){
			s[j--]=p[l].id;
		}
		cout<<s[1];
		for(int i=2;i<=len;i++){
			cout<<' '<<s[i];
		}
		cout<<endl;
		t=t+len;
	}
	return 0;
}

双指针做法
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 10010;

int n, m;
struct Person
{
    string name;
    int h;
    bool operator< (const Person &t) const
    {
        if (h != t.h) return h > t.h;
        return name < t.name;
    }
}p[N];
string line[N];

int main()
{
    cin >> n >> m;

    for (int i = 0; i < n; i ++ ) cin >> p[i].name >> p[i].h;
    sort(p, p + n);

    for (int i = 0, j = 0; i < m; i ++ )
    {
        int len = n / m;
        if (!i) len += n % m;  // 特判最后一排
        for (int r = len / 2 + 1, l = r - 1; l > 0 || r <= len; l --, r ++ )
        {
            if (r <= len) line[r] = p[j ++ ].name;
            if (l > 0) line[l] = p[j ++ ].name;
        }

        cout << line[1];
        for (int k = 2; k <= len; k ++ ) cout << ' ' << line[k];
        cout << endl;
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王子y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值