PAT Basic 1055. 集体照

发布时间 2023-03-31 10:47:59作者: 十豆加日月

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