PAT Basic 1055. 集体照
PAT Basic 1055. 集体照
1. 题目描述:
拍集体照时队形很重要,这里对给定的 \(N\) 个人 \(K\) 排的队形设计排队规则如下:
- 每排人数为 \(N/K\)(向下取整),多出来的人全部站在最后一排;
- 后排所有人的个子都不比前排任何人矮;
- 每排中最高者站中间(中间位置为 \(m/2+1\),其中 \(m\) 为该排人数,除法向下取整);
- 每排其他人以中间人为轴,按身高非增序,先右后左交替入队站在中间人的两侧(例如5人身高为190、188、186、175、170,则队形为175、188、190、186、170。这里假设你面对拍照者,所以你的左边是中间人的右边);
- 若多人身高相同,则按名字的字典序升序排列。这里保证无重名。
现给定一组拍照人,请编写程序输出他们的队形。
2. 输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出两个正整数 \(N\)(\(≤10^4\),总人数)和 \(K\)(\(≤10\),总排数)。随后 \(N\) 行,每行给出一个人的名字(不包含空格、长度不超过 8 个英文字母)和身高([30, 300] 区间内的整数)。
3. 输出格式:
输出拍照的队形。即K排人名,其间以空格分隔,行末不得有多余空格。注意:假设你面对拍照者,后排的人输出在上方,前排输出在下方。
4. 输入样例:
10 3
Tom 188
Mike 170
Eva 168
Tim 160
Joe 190
Ann 168
Bob 175
Nick 186
Amy 160
John 159
5. 输出样例:
Bob Tom Joe Nick
Ann Mike Eva
Tim Amy John
6. 性能要求:
Code Size Limit
16 KB
Time Limit
400 ms
Memory Limit
64 MB
思路:
根据题意需要先将拍照的人按照身高和名字排序,这里定义一个结构体student
用于存储每个人的信息,然后调用库函数qsort
进行排序。关键在于每一排输出的处理,这里题目要求每一排最高的人站在中间,然后左右交替排列,我的思路就是定义子函数void generateSeq(int *pInt, int numCount)
用于生成每一排的顺序序列,然后维护一个outputCount
对每一排进行输出。
这里第一次提交时testpoint3,4,5都报wrong answer,检查代码感觉无逻辑问题,就去处理一些边界条件。。。比如只有1排的情况,或是人数小于排数的情况,结果还是wrong answer。。。无奈只能参考大佬题解:1055. 集体照 (25)-PAT乙级真题_柳婼的博客-CSDN博客 感觉没什么特别处理的地方,最后发现是strcmp
库函数返回值的问题。。。我编写代码时以为strcmp
只会返回-1,0,1这三种值,所以在编写cmp()
函数是给身高和姓名分别分了10和1的权重,但其实ANSI标准规定strcmp
会返回正数、负数和0,具体值是依赖实现的,最后我把身高的权重改为100后AC(其实应该换种写法的,这里懒得改了)。
My Code:
#include <stdio.h>
#include <string.h> // strcmp header
#include <stdlib.h> // malloc header, qsort header
typedef struct student
{
char name[9];
int height;
} Student;
int cmp(const void *p1, const void *p2);
void generateSeq(int *pInt, int numCount);
// first submit testpoint3, 4, 5 wrong answer
int main(void)
{
int headCount = 0;
int rowNum = 0;
Student *pStudent = NULL;
int i=0; //iterator
int lastRowNum = 0;
int perRowNum = 0;
int *pLast = NULL;
int *pPer = NULL;
int outputCount = 0;
int j=0; //iterator
scanf("%d%d", &headCount, &rowNum);
pStudent = (Student *)malloc(sizeof(Student) * headCount);
for(i=0; i<headCount; ++i)
{
scanf("%s%d", pStudent[i].name, &pStudent[i].height);
}
//void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
qsort(pStudent, headCount, sizeof(Student), cmp); //descend order
// for(i=0; i<headCount; ++i) // test sort result
// {
// printf("%s %d\n", pStudent[i].name, pStudent[i].height);
// }
perRowNum = headCount / rowNum;
if(!perRowNum) // if N < K
{
rowNum = 1;
perRowNum = headCount;
}
if(rowNum > 1)
{
lastRowNum = headCount - perRowNum * (rowNum-1);
}
else // if only have one row
{
lastRowNum = 0;
}
pPer = (int *)malloc(sizeof(int) * perRowNum);
pLast = (int *)malloc(sizeof(int) * lastRowNum);
generateSeq(pPer, perRowNum);
generateSeq(pLast, lastRowNum);
// for(i=0;i<lastRowNum; ++i) // test generated sequence is correct
// {
// printf("%d ", pLast[i]);
// }
// printf("\n");
// for(i=0;i<perRowNum; ++i)
// {
// printf("%d ", pPer[i]);
// }
if(lastRowNum>0)
{
for(i=0; i<lastRowNum; ++i) //output last row
{
if(!i)
printf("%s", pStudent[pLast[i]].name);
else
printf(" %s", pStudent[pLast[i]].name);
}
printf("\n");
}
outputCount = lastRowNum;
// for(i=1; i<rowNum; ++i) //output other row
// {
while(outputCount < headCount)
{
for(j=0; j<perRowNum; ++j)
{
if(!j)
printf("%s", pStudent[pPer[j]+outputCount].name);
else
printf(" %s", pStudent[pPer[j]+outputCount].name);
}
printf("\n");
outputCount+=perRowNum;
}
// }
free(pStudent);
free(pPer);
free(pLast);
return 0;
}
// when change the height' weight from 10 to 100, the testpoint3, 4, 5 accepted...
int cmp(const void *p1, const void *p2)
{
Student *stu1 = (Student *)p1;
Student *stu2 = (Student *)p2;
return (((*stu2).height - (*stu1).height)*100 + strcmp((*stu1).name, (*stu2).name));
}
void generateSeq(int *pInt, int numCount)
{
int flag = 1;
int count=0;
int middle = numCount/2+1 -1;
if(!numCount) return; // if numCount is null.
pInt[middle] = count;
++count;
while(count < numCount)
{
pInt[middle-flag] = count;
++count;
if(count == numCount) break;
pInt[middle+flag] = count;
++count;
++flag;
}
}
// void generateSeq(int *pInt, int numCount)
// {
// int middle = numCount/2+1 -1;
// int i=0, j=0;
// if(!numCount) return; // if numCount is null.
// pInt[middle] = 0;
// j = middle - 1;
// for(i=1; i<numCount; i+=2)
// {
// pInt[j--] = i;
// }
// j = middle+1;
// for(i=2; i<numCount; i+=2)
// {
// pInt[j++] = i;
// }
// }