PAT (Advanced Level) Practice 1062 Talent and Virtue & PAT (Basic Level) Practice 1015 德才论

一、概述

给出N个考生的考生号,德成绩和才成绩,根据规则排序输出。

排序题,但我一般用的只有冒泡排序。所以最开始就按最简单的模拟做法来做:开五个结构数组,输入然后判断,存入不同数组,存完之后对四个数组分别冒泡,再分别输出。先不考虑空间是否超了,只是时间复杂度就难以接受。对于最大值100000,冒泡需要的时间为一百亿的数量级,按一秒1Ghz,那么冒泡便需要一秒以上的时间,这样来说绝对会超时了,因此是不可取的。因此需要用到两个函数:cmp和sort。

二、分析

本题的考点在于,如何在规定时间内对大量数据进行排序,使用cmp和sort完成较好。

使用这两个函数,要添加头文件algorithm。

首先采用结构体保存每个学生的成绩,选择的变量类型有讲究。

struct TandV{
	char ID_Number[10];
	int Virtue_Grade;
	int Talent_Grade;
	int sum;
	int flag;
}TV[100000];

首先是学生的考生号,注意到考生号是可能会比较大小的,同时它的位数固定,也较长,因此不推荐用long long int,使用string或者char较好,使用string时,比较大小函数用compare,使用char数组时,比较函数使用strcmp。我这里选择使用char,原因在于char数组可以使用scanf和%s输入,提高效率,string就只能用cin了,数量多时可能超时。

然后是成绩,简单使用int即可。

注意,为了便于分类,使用flag来区别不同的学生,同时有助于排序。这是极大提高效率和可读性的一步。

sort函数十分好用,它有三个变量,第一个是待排数组的首地址,第二个是末地址的下一个地址,第三个是cmp函数的返回值。

如果不填入cmp那个变量,sort默认是从小到大对数组元素进行排序。如果想按其他方式排序呢?这就是我们使用cmp函数的意义。

cmp函数,实际上就是一种规则,规定了如何排序,常见的cmp函数长这样

bool cmp(int a,int b)
{
    return a<b;//按从小到大排列
}

复杂一点的cmp函数长这样

bool cmp(Stu a,Stu b)
{
    if(a->math!=b->math)
        return a->math<b->math;//按数学成绩从小到大排列
    else
        return a->chinese>b->chinese;//如果数学成绩相同,按语文成绩从小到大排列
}

注意到cmp的返回值是bool类型,这意味着它只返回对或者错,那么即使不了解sort的工作原理,我们也可以想象,cmp就是负责告诉sort是否要换两个元素位置,如果返回真,则交换,返回假,则不交换(当然也可能反过来),那么重点就在cmp上了,cmp负责看到底交换不交换两个元素,我们的逻辑主要也在这上面。代码如下:

bool cmp(TandV a,TandV b)
{
	if(a.flag!=b.flag)//如果不是同一组 
		return a.flag<b.flag;//按圣人、君子、愚人、小人排序 
	else if(a.sum!=b.sum)
		return a.sum>b.sum;//同一组,按总分排序 
	else if(a.Virtue_Grade!=b.Virtue_Grade)
		return a.Virtue_Grade>b.Virtue_Grade;//同一组且总分相同,按德成绩排序 
	else
		return strcmp(a.ID_Number,b.ID_Number)<0;//都相同,按学号排序 
}

注意以下几点:

if的判断条件都是!=,不是大于或小于;

return后面不是int时,char比较不能只把strcmp放上,要加上<0,这说明是按考生号从小到大排列,>0就是从大到小排列了。

然后是分类,给flag赋值。代码如下:

if(TV[i].Virtue_Grade<L||TV[i].Talent_Grade<L)
				TV[i].flag=5;
else if(TV[i].Virtue_Grade>=H&&TV[i].Talent_Grade>=H)
	{
		TV[i].flag=1;
		_num++;
	}
else if(TV[i].Virtue_Grade>=H&&TV[i].Talent_Grade<H)
	{
		TV[i].flag=2;
		_num++;		
    }
else if(TV[i].Virtue_Grade<H&&TV[i].Talent_Grade<H&&TV[i].Virtue_Grade>=TV[i].Talent_Grade)
	{
		TV[i].flag=3;
		_num++;
	}
else
	{
		TV[i].flag=4;
		_num++;
	}

注意一点,判断条件的顺序不能出错,要首先判断是不是都大于等于L,这样下面的条件可以简单不少;

再之后就是输入数据,排序和输出了。

有了sort函数,排序变得简单了很多啊,也不需要自己去苦兮兮的去写垃圾的冒泡了。

三、总结

要重视cmp和sort的使用,排序题中很常用,很重要,同时注意char数组的比较。

PS:代码如下:

#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;

struct TandV{
	char ID_Number[10];
	int Virtue_Grade;
	int Talent_Grade;
	int sum;
	int flag;
}TV[100000];

bool cmp(TandV a,TandV b)
{
	if(a.flag!=b.flag)//如果不是同一组 
		return a.flag<b.flag;//按圣人、君子、愚人、小人排序 
	else if(a.sum!=b.sum)
		return a.sum>b.sum;//同一组,按总分排序 
	else if(a.Virtue_Grade!=b.Virtue_Grade)
		return a.Virtue_Grade>b.Virtue_Grade;//同一组且总分相同,按德成绩排序 
	else
		return strcmp(a.ID_Number,b.ID_Number)<0;//都相同,按学号排序 
}

int main()
{
	long int num;
	scanf("%ld",&num);
	int H,L;
	scanf("%d %d",&L,&H);
	int i;
	long int _num=0;
	for(i=0;i<num;i++)
	{
		scanf("%s %d %d",&TV[i].ID_Number,&TV[i].Virtue_Grade,&TV[i].Talent_Grade);
		TV[i].sum=TV[i].Talent_Grade+TV[i].Virtue_Grade; 
		if(TV[i].Virtue_Grade<L||TV[i].Talent_Grade<L)
				TV[i].flag=5;
		else if(TV[i].Virtue_Grade>=H&&TV[i].Talent_Grade>=H)
			{
				TV[i].flag=1;
				_num++;
			}
		else if(TV[i].Virtue_Grade>=H&&TV[i].Talent_Grade<H)
			{
				TV[i].flag=2;
				_num++;
			}
		else if(TV[i].Virtue_Grade<H&&TV[i].Talent_Grade<H&&TV[i].Virtue_Grade>=TV[i].Talent_Grade)
			{
				TV[i].flag=3;
				_num++;
			}
		else
			{
				TV[i].flag=4;
				_num++;
			}
	}
	sort(TV,TV+num,cmp);
	printf("%ld\n",_num);
	for(i=0;i<_num;i++)
	{
		printf("%s %d %d\n",TV[i].ID_Number,TV[i].Virtue_Grade,TV[i].Talent_Grade);
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值