德才论

(一) 问题归纳

题目来源:https://www.nowcoder.com/pat/6/problem/4041 转载自牛客网
在读过题目之后,我们可以提出如下几个问题:
1.用什么数据结构来表示学员的信息?
2.如何对学员进行分类?分类后如何记录?
3.分类后如何进行排序?

(二) 问题解析

1.学员的信息包括:编号、德分、才分和总分,首先,先入为主采用结构体记录学员信息,可是学员数量是用户输入的,是个变量。如果用结构体静态数组,那么他的数量是不确定的,所以采用结构体动态数组,用malloc函数构造动态数组来记录学员信息。
复习语法:
1.静态数组和动态数组
如果数组个数不确定的情况,通常采用malloc函数构造动态数组

数据类型 *a=((数据类型 *)malloc(m*sizeof(数据类型)));

注意malloc函数返回的是void型的数据,必须进行数据类型的强制转换。
2.结构体和结构体指针

typedef struct {
int num;
int cai;
int de;
int score;
}infor;

结构体访问数据一般是用“.”这个成员运算符访问结构体成员:

infor a={10000001,80,90};
a.num=1000002,a.cai=80,a.de=90;

结构体指针访问数据则是用"->"这个符号访问结构体成员

infor *b=&a;
b->num=100001;

3.动态数组的访问:
动态数组访问不可以直接用索引值,如:

infor *a=((infor *)malloc(m*sizeof(infor)));
a[i].num=10000;//这个是错误的
(a+i)->num=10000;//这个是正确的

2.学员的分类通过l,h这两个标准进行划分分为四类等级,读懂题意即可,排序则是按照总分,德分,编号三种标准进行层层排序,并不只是按照一个标准。
3.这里排序采用的是选择排序,不过需要进行多选择判断,算是一个选择排序的升级版

void sort (infor *a,int f[],int k)
{//选择排序
  int m,temp;
  for(int i=0;i<k;i++)
  {
   m=i;
   for(int j=i+1;j<k;j++)
   {//选择总分大的
    if((a+f[j])->score>(a+f[m])->score)
        m=j;
    else if((a+f[j])->score==(a+f[m])->score)
    {//总分相同,选择德分大的
        if((a+f[j])->de>(a+f[m])->de)
          m=j;
        else if((a+f[j])->de==(a+f[m])->de){
            //德分相同,选择编号小的
            if((a+f[j])->num<(a+f[m])->num)
                m=j;
        }
    }
   }
   temp=f[i],f[i]=f[m],f[m]=temp;
  }
}

4.排序算法:选择排序

(三)问题源码

#include <iostream>
#include<stdlib.h>
using namespace std;
typedef struct {
int num;
int cai;
int de;
int score;
}infor;
void sort (infor *a,int f[],int k)
{//选择排序
  int m,temp;
  for(int i=0;i<k;i++)
  {
   m=i;
   for(int j=i+1;j<k;j++)
   {//选择总分大的
    if((a+f[j])->score>(a+f[m])->score)
        m=j;
    else if((a+f[j])->score==(a+f[m])->score)
    {//总分相同,选择德分大的
        if((a+f[j])->de>(a+f[m])->de)
          m=j;
        else if((a+f[j])->de==(a+f[m])->de){
            //德分相同,选择编号小的
            if((a+f[j])->num<(a+f[m])->num)
                m=j;
        }
    }
   }
   temp=f[i],f[i]=f[m],f[m]=temp;
  }
}

void print(infor *a,int f[],int k)
{//输出信息
 for(int i=0;i<k;i++)
 {
     cout<<(a+f[i])->num<<" "<<(a+f[i])->de<<" "<<(a+f[i])->cai<<endl;
 }
}

int main()
{
    int m,l,h,f1[100000],f2[100000],f3[100000],f4[100000];
    int k1=0,k2=0,k3=0,k4=0;
    cin>>m>>l>>h;
    infor *a=((infor *)malloc(m*sizeof(infor)));
    for(int i=0;i<m;i++)
    {//输入信息
      cin>>(a+i)->num;//输入编号
      cin>>(a+i)->de;//“德”分
      cin>>(a+i)->cai;//"才"分
      (a+i)->score=(a+i)->de+(a+i)->cai;//总分
    }
    for(int i=0;i<m;i++)
    {//分类
     if((a+i)->de>=h&&(a+i)->cai>=h)
        f1[k1++]=i;
     else if((a+i)->de>=h&&(a+i)->cai<h&&(a+i)->cai>=l)
        f2[k2++]=i;
     else if((a+i)->de<h&&(a+i)->de>=l&&(a+i)->cai<h&&(a+i)->cai>=l&&(a+i)->de>=(a+i)->cai)
        f3[k3++]=i;
     else if((a+i)->de>=l&&(a+i)->cai>=l)
        f4[k4++]=i;
    }
    //排序
    sort(a,f1,k1);
    sort(a,f2,k2);
    sort(a,f3,k3);
    sort(a,f4,k4);
    cout<<k1+k2+k3+k4<<endl;
    print(a,f1,k1);
    print(a,f2,k2);
    print(a,f3,k3);
    print(a,f4,k4);
    free(a);
    a=NULL;
    return 0;
}
根据给出的输入样例,我们可以看到有14位考生的信息。每位考生的信息包括准考证号、分和才分。其中,考生的准考证号是8位整数,分和才分都是在区间[0, 100]内的整数。接下来是要输出的内容。第一行输出的是达到最低分数线的考生人数M,接下来的M行按要求输出考生的信息。考生按照总分从高到低排序,如果总分相同,则按照分降序排列,如果分也相同,则按照准考证号升序输出。 根据这个规则,我们可以找到准考证号为1015的考生在测试点2的输出结果。在输出样例中,M的值为12,表示符合要求的考生人数为12人。接下来的M行按要求输出了考生的信息,其中包括准考证号、分和才分。 所以,要找到1015德才论测试点2的结果,我们需要找到输出样例中的准考证号为1015的考生信息。最后的输出结果为:10000013 90 99 。 因此,准考证号为1015的考生在德才论测试点2的输出结果是10000013,分为90,才分为99。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [1015 德才论 (25 分)+测试点](https://blog.csdn.net/xyqqwer/article/details/89313345)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值