PAT (Basic Level) Practice (中文)1055 集体照 (25 分)

PAT (Basic Level) Practice (中文)1055 集体照 (25 分)

题目描述:

拍集体照时队形很重要,这里对给定的 N 个人 K 排的队形设计排队规则如下:

  • 每排人数为 N/K(向下取整),多出来的人全部站在最后一排;
  • 后排所有人的个子都不比前排任何人矮;
  • 每排中最高者站中间(中间位置为 m/2+1,其中 m 为该排人数,除法向下取整);
  • 每排其他人以中间人为轴,按身高非增序,先右后左交替入队站在中间人的两侧(例如5人身高为190、188、186、175、170,则队形为175、188、190、186、170。这里假设你面对拍照者,所以你的左边是中间人的右边);
  • 若多人身高相同,则按名字的字典序升序排列。这里保证无重名

现给定一组拍照人,请编写程序输出他们的队形。

输入格式:

每个输入包含 1 个测试用例。每个测试用例第 1 行给出两个正整数 N(≤10^4,总人数)和 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
题目要求:
作者           CHEN, Yue
单位           浙江大学
代码长度限制     16 KB
时间限制        400 ms
内存限制        64 MB
解题思路:

首先是对所有人员的处理 ,需要按照题目要求对输入的人员的人名以及身高进行排序。这里我利用的是 struct 结构体sort 函数 分别进行存储数据和排序。

// 第一存储姓名和身高的结构体 peo typedef 的好处自行体会哦!
typedef struct peo{
	string name ;		// string 类型 用来存储人名 name (因为 string 的比较就是字典序)
	int high ;			// int 类型 用来存储与 name 对应的 身高值 high
} Peo; 

// 为满足题目要求,手撕与 sort 配合使用的 cmp 函数
bool cmp(Peo a , Peo b){ 
	if(a.high == b.high)
		return a.name < b.name ;   // 身高相同的时候, 按照人名的 字典序升序进行排列
	return a.high > b.high ;	// 身高不等时,按照身高的降序排列
}


sort(stu , stu + n , cmp) ; // 对输入的数据 按要求排序,n 为输人的需要排序的人数

然后是将上述中排好序的人,进行排集体照的站位。总共有 k 排,除最后一排外,其余排的人数 x = n / k ,故最后一排的人数为 y = n - (k - 1) * x ; 其实接下来就变成了设计一个函数来排好第 m 排的集体照站位即可。

 // 定义一个二维的 string 类型的数组,用来存储 集体照的站位
string  s[10][10005]; 
// 设计一个排集体照第 k 行站位的 函数
void sortPeople(int row , int num){  // 参数说明: 第 row 排 以及该排的人数 num 个
	int t = num / 2 + 1 ;	// 首先找到 这一排最高的那个人的站位 t 	
	// 计算出在排这一排之前,我们已经有多少人的站位已确定
    int index = (row == 0) ? 0 : (row - 1) * x + y ;
     // 将剩下最高的人,安置他的站位 t -1  (t - 1)是因为从 0 开始计算
	s[row][t - 1] = stu[index].name ;  
	// 排好中间人后,按照题目要求,中间人为轴先右后左,(对应我们存数据的先低位后高位)
    // 先将他的低位排好,因为是先低位后高位,依次轮流 , j 的初值为 1 , 步长为 2
    for( int i = t - 2 , j = 1 ; i >= 0 ; i -- , j += 2){
		s[row][i] = stu[index + j].name ;
	}
    // 再将他的高位排好,因为是先低位后高位,依次轮流 , j 的初值为 2 , 步长为 2
	for( int i = t , j = 2 ; i < num ; i ++ , j += 2){
		s[row][i] = stu[index + j].name ;
	}
    // 排完左边和右边,本排的 集体照站位 已经全部完成。
}

最后是对每一排调用一下 sortPeople() 函数

// 最后一排的人数与其他排不一致,先排好最后一排
sortPeople(0 , y)	;
// 剩下的 k - 1 排,直接利用 for 循环进行调用即可
for(int i = 1 ; i < k ; i ++){
		sortPeople(i , x)	;
}
完整代码:
#include<bits/stdc++.h>
using namespace std ;
#define MAX 10005
typedef struct peo {
	string name ;
	int high ;
} Peo ; 
Peo stu[MAX] ;
int n , k , x , y ;
string  s[10][MAX];
bool cmp(Peo a , Peo b){
	if(a.high == b.high)
		return a.name < b.name ;
	return a.high > b.high ;
}
// 从最后一排开始,往前排 
void sortPeople(int row , int num){   // 第 row 排 以及该排的人数 num 个
	int t = num / 2 + 1 ;
	int index = (row == 0) ? 0 :(row - 1 * x + y ;// 前面已经排了index个人了 
	s[row][t - 1] = stu[index].name ;
	for( int i = t - 2 , j = 1 ; i >= 0 ; i -- , j += 2){
		s[row][i] = stu[index + j].name ;
	}
	for( int i = t , j = 2 ; i < num ; i++ ,j += 2){
		s[row][i] = stu[index + j].name ;
	} 	
}
int main(){	
	cin >> n >> k ;
	for(int i = 0 ; i < n ; i++){
		cin>>stu[i].name>>stu[i].high;
	}
	sort(stu , stu + n , cmp) ;// 按照题目要去排序; 
//	for(int i = 0 ; i < n ; i++){
//		cout<<stu[i].name<<stu[i].high<<endl;
//	}
	x = n / k ;	// 前 k-1排人数 
	y = n - (k - 1 ) * x;	// 最后一排的人数 
	sortPeople(0 , y)	;
	for(int i = 1 ; i < k ; i++){
		sortPeople(i , x)	;
	}
	cout<<s[0][0] ;
	for(int i = 1 ; i < y ; i++){
		cout<<" "<<s[0][i] ;
	}
	for(int i = 1 ; i < k ; i++){
		cout<<endl ;
		cout<<s[i][0] ;
		for(int j = 1 ; j < x ; j ++){
			cout<<" "<<s[i][j] ;
		}
	}
	cout<<endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lingchen0522

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

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

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

打赏作者

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

抵扣说明:

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

余额充值