1109 Group Photo (25 分)笔记

1109 Group Photo (25 分)

题意

给出n个学生的信息(身高和姓名),要求你给这群学生排列一个队形,类似于拍毕业照的队形。队形的要求有以下几点:
1.排列有m行,每行有n/m搁学生,多余的学生排到最后一行(最后一行可以不是n/m个学生)
2.前排的学生不能比后排高
3.一排中最高的站在中间(s/2+1的位置,s为该行的总人数)
4.其他人按非递增顺序往两边排列,先左后右(如 1 2 3 4 5 排列后为 2 4 5 3 1)
5.身高相同按名字字典序递增排列,名字字典序小的先排。
输出最后的队形。(从后往前输出)

解题过程

wa了两发,一是没搞明白char字符串重载运算的问题,cmp返回的是true和false,重载中是小于号就会升序,大于号降序。char不能直接用符号比较,得用strcmp函数得出两个字符的差值(前减后),再根据差值返回true和false。
二是没考虑清楚按名字字典序小先排的概念(与我的方法得到的结果不同)我先给所有同学按身高和名字排了个序,身高相同名字字典序一样的排在前面,这里误理解为先排就应该是排在前面,后面仔细考虑发现先排是离中间最近,优先在左。修改之后就过了。

思路

给同学们排个序,高的在后,身高相同按名字字典序降序排序,名字字典序大的在前。尽可能让高的人在后面,高的人在中间,矮的人在前面与两边。
考虑每行要求高的在中间,计算一下位置。
若该行有5个人,1,2,3,4,5他们的位置应该是2 4 5 3 1,可以看出前两个人下标为递增的偶数,后三个人下表为递减的奇数。
若有4个人 1,2,3,4 他们的位置为1 3 4 2,可以看出前两个数下标为递增奇数,后两个下标为递减偶数。
分成前后两段求取每个坐标即可。

remark

题目虽然过了,但有bug,不知道是我理解岔了还是数据太水了。
题目说身高相同按字典序递增排列,看这个样例:
2 2
a 100
aa 200
b 200
c 300
我的运行结果为
aa c
a b

按题意因该为
b c
a aa

代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct node{
	char name[101];
	int height;
}node;
bool cmp(node x,node y)
{
	if(x.height==y.height){
		if(strcmp(x.name,y.name)>0){
			return true;
		}else{
			return false;
		}
	}
	return x.height<y.height;
}
node student[20007];
char fm[21][2007][11];
int n,m,row,temp=0,last;	//temp前面已经排好的人数,row每行的人数,last最后一行人数
int main()						
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%s %d",&student[i].name,&student[i].height);
	}
	sort(student+1,student+n+1,cmp);
	row=n/m;
	for(int i=1;i<m;i++){
		if(row%2==0){
			for(int j=1;j<=row/2;j++){
				strcpy(fm[i][j],student[temp+2*j-1].name);
			}
			for(int j=row/2+1;j<=row;j++){
				strcpy(fm[i][j],student[temp+2*row+2-2*j].name);
			}
		}else{
			for(int j=1;j<=(row-1)/2;j++){
				strcpy(fm[i][j],student[temp+j*2].name);
			}
			for(int j=(row+1)/2;j<=row;j++){
				strcpy(fm[i][j],student[temp+2*row+1-2*j].name);
			}
		}
		temp+=row;
	}
	last=n-temp;
	if(last%2==0){
			for(int j=1;j<=last/2;j++){
				strcpy(fm[m][j],student[temp+2*j-1].name);
			}
			for(int j=last/2+1;j<=last;j++){
				strcpy(fm[m][j],student[temp+2*last+2-2*j].name);
			}
		}else{
			for(int j=1;j<=(last-1)/2;j++){
				strcpy(fm[m][j],student[temp+j*2].name);
			}
			for(int j=(last+1)/2;j<=last;j++){
				strcpy(fm[m][j],student[temp+2*last+1-2*j].name);
			}
		}
		temp+=last;
		for(int j=1;j<=last;j++){
			if(j!=1){
				printf(" ");
			}
			printf("%s",fm[m][j]);
		}
		printf("\n");
		for(int i=m-1;i>0;i--){
			for(int j=1;j<=row;j++){
				if(j!=1){
					printf(" ");
				}
				printf("%s",fm[i][j]);
			}
			printf("\n");
		}
		return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值