《算法笔记上机实验指南》第4章 入门篇(2)---算法初步 4.1排序

pat A1012

单词:

Each input file contains one test case. 每个输入文件包含一个测试用例
corresponding 相应的
separated by a space 空格隔开
Hence 所以


题意:

输入:

1.输入n,m
2.输入n个学生的id C M E(学生编号,C语言成绩,数学成绩,英文成绩)
3.输入m个要查询的学生id

输出:

1.对应
2.输出学生编号,总排名,考场位置,数组在考场内的排名
3.排名原则:成绩不同,降序排列;否则,按照编号的升序排列


特殊技巧:排名的实现

分数不同的排名不同,分数相同但占用一个位置,比如5个学生分数分别为90 88 88 88 86 (注意成绩必须是倒叙排列)那么这5个学生排名是1 2 2 2 5

第一种方法:

从数组下标为0开始的排名为1,然后遍历其余部分;如果此人分数与前人相同,则排名不变;否则,排名为数组下标+1。

stu[0].r=1;
for(int i=1; i<n; i++)
{
   
	if(stu[i].score==stu[i-1].score)
		stu[i].r=stu[i-1].r
	else
		stu[i].r=i+1;
}

第二种方法:

有时题目不需要将排名记录下来,而是直接输出。可以令int类型的变量r为1,然后遍历所有个体;如果当前个体不是第一个且当前个体的分数不等于上一个个体的分数,则r=数组下标+1,此时r就是当前个体的排名。这样的做法适用于输出信息过多,导致第一种方法代码冗长。

int r=1;
for(int i=0; i<n; i++)
{
   
	if(i>0 && stu[i].score!=stu[i-1].score)
		r=i+1;
	cout << r;  //或者stu[i].r=r; 
}

解题思路:

1.由于要有总排名,考场排名…所以在定义结构时将这些内容加进去
2.cmp排序要求是:成绩不同,按照成绩降序排列,否则按照id的升序排列
3.主函数:
     1.输入信息,并在其考场内进行排序,按照书上第1中方法确定location_number和local_rank
     2.对整个结构数组排序,然后书上第2中方法,按要求输出

参考代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
/*
    解题思路:
    1.设置数组结构:6位整数学生id,数组grade表示学生的4个成绩
    2.设置字符数组course[4]按照优先级顺序ACME,设置二维数组:下标为学生编号,元素值为学生每一门科目所对应的排名。这样就可以通过找到排名最小(也就是成绩最大)的学生最擅长的科目去对应标签
    3.cmp表示按照成绩的降序排列
    4.main:
        1.输入成绩并计算出平均分
        2.对每一科目成绩先排名+按书上排名法1算出每个人每个科目对应的排名
        3.输入要查询的id,如果不存在,则输出NA;否则,在对应的id那一维数组中找出排名最小的,然后取对应course中的ACME标签
    5.这里有一个重要的思想:
        1.题目要求是先找出每个人CME课程中成绩最大的,并输出该科目对应拍名;如果成绩最大的不止1个,则其标签为A
        2.代码中的思想是直接对每个人的每个科目排名,找出排名最小的(对应成绩最大的)也就是学生最擅长的
    
*/
struct Student
{
   
    int id;  //存放6位整数的ID
    int grade[4];   //存放4个分数
}stu[2010];

char course[4]={
   'A','C','M','E'};   //按优先级顺序,方便输出
int Rank[10000000][4]={
   0};   //Rank[id][0]~Rank[id][4]为4门课对应的排名
int now;    //cmp函数中使用,表示当前按now号分数排序stu数组

bool cmp(Student a, Student b)   //stu数组按now号分数递减排序
{
   
    return a.grade[now] > b.grade[now];
}

int main()
{
   
    int n,m;
    scanf("%d%d",&n,&m);
    //读入分数,其中grade[0]~grade[3]分别表示A,C,M, E;
    for(int i=0; i<n; i++)
    {
   
        scanf("%d%d%d%d", &stu[i].id,&stu[i].grade[1], &stu[i].grade[2], &stu[i].grade[3]);
        stu[i].grade[0]=(stu[i].grade[1] + stu[i].grade[2] + stu[i].grade[3])/3.0+0.5; //四舍五入算平均分
    }

    for(now=0; now<4; now++)  //对每一个人的每个成绩进行排名
    {
   
        //枚举A,C,M, E 4个中的一个
        sort(stu,stu+n,cmp);   //对所有考生按分数从大到小排序
        Rank[stu[0].id][now]=1;   //排序玩,将分数最高的设为rank1
        for(int i=1; i<n; i++)
        {
   
            //对于剩下的考生
            //若与前一位考生分数相同
            if(stu[i].grade[now] == stu[i-1].grade[now])
            {
   
                Rank[stu[i].id][now]=Rank[stu[i-1].id][now];  //则他们排名相同
            }
            else
            {
   
                Rank[stu[i].id][now]=i+1;   //否则,为其设置正确的排名
            }
        }
    }
    
    //输出内容
    int query;  //查询考生的id
    for(int i=0; i<m; i++)
    {
   
        scanf("%d", &query);
        if(Rank[query][0]==0)
        {
   
            //如果这个考生的id不存在,则输出n/a
            printf("N/A\n");

        }
        else
        {
   
            int k=0; //选出Rank[query][0~3]中最小的(rank值越小,排名越高)
            for(int j=0; j<4; j++)
            {
   
                if(Rank[query][j] < Rank[query][k])
                {
   
                    k=j;
                }
            }
            printf("%d %c\n",Rank[query][k],course[k]);
        }
    }
    return 0;
}


注意事项:

1.student结构中,字符数组char id[15],在用scanf输入时,不用在前面加取址符&

scanf("%s %d",stu[num].id,&stu[num].score);
  1. 用sort来对普通数组进行排序
sort(stu,stu+num,cmp);   //数组名 数组名+数组长度

知识总结:

1.strcmp(a,b)用来从左至右比较两个char型数组的字典序大小

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
   
    char a[3];
    char b[3];
    scanf("%s %s",a,b);
    //当a的字典序列>b的字典序列时,返回正数

    //当a的字典序列<b的字典序列时,返回复数

    //当a的字典序列=b的字典序列时,返回0

}


pat A1016

单词:

non-negative 非负的
integers 整数
a positive number 正数
is paired with 与…配对
chronologically 按年代次序地
guaranteed 保证
alphabetical 按字母顺序的
the lasting time 持续时间
the charge of the call 电话费


题意:

输入:

1.输入24个时间段所对应的每分钟多少美分(如下图所示)
在这里插入图片描述
2.输入n(表示共有n条通话记录)
3.输入具体记录包括名字(有20个单词组成)时间(月份,日期,几点,几分)字符串"on-line"或者“off-line”

输出:

1.输出顺序首先按照客户的姓名的字符串的升序排列和按照时间的顺序排列,排完后如下图所示
在这里插入图片描述
2.对于每一个人,有一个on-line和off-line想对应,如果on-line没有对应的off-line相对应,则忽视;同样off-line也是如此
3.对于每次输出先输出客户姓名和对应的月份,按照例子中的格式
4.对于每次的通话,输出开始时间和结束时间,格式按照日期,几点,几分,然后再输出每次通话的费用
5.最后输出总费用
对于电话费的计算方式如下图所示:
在这里插入图片描述


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值