PAT(Basic Level) Practice(中文) 1015德才论

2023-10-05 00:30

本文主要是介绍PAT(Basic Level) Practice(中文) 1015德才论,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

※  PTA是 程序设计类实验辅助教学平台 ,里边包含一些编程题目集以供练习。

这道题用java解,我试了三种解法,不断优化,但始终是三个测试点通过、三个测试点超时。我把我的代码放在这里,做个参考吧。

1015 德才论 题目

    题目    

作者 CHEN, Li

单位 浙江大学

宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。”

现给出一批考生的德才分数,请根据司马光的理论给出录取排名。

输入格式:

输入第一行给出 3 个正整数,分别为:N(≤10^5),即考生总数;L(≥60),为录取最低分数线,即德分和才分均不低于 L 的考生才有资格被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到但德分到优先录取线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于 H,但是德分不低于才分的考生属于“才德兼亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线 L 的考生也按总分排序,但排在第三类考生之后。

随后 N 行,每行给出一位考生的信息,包括:准考证号 德分 才分,其中准考证号为 8 位整数,德才分为区间 [0, 100] 内的整数。数字间以空格分隔。

输出格式:

输出第一行首先给出达到最低分数线的考生人数 M,随后 M 行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。

输入样例:

14 60 80
10000001 64 90
10000002 90 60
10000011 85 80
10000003 85 80
10000004 80 85
10000005 82 77
10000006 83 76
10000007 90 78
10000008 75 79
10000009 59 90
10000010 88 45
10000012 80 100
10000013 90 99
10000014 66 60

输出样例:

12
10000013 90 99
10000012 80 100
10000003 85 80
10000011 85 80
10000004 80 85
10000007 90 78
10000006 83 76
10000005 82 77
10000002 90 60
10000014 66 60
10000008 75 79
10000001 64 90

 


代码    

我用java写了三种解法,测试结果都是三个测试点正确、三个测试点超时。研究半天也没搞明白到底为什么超时(难道是只能用C语言才不会超时?),发出来做个参考吧。

解法一  

用二维数组存储学生信息,同时用这个数组作为静态链表来排序(定义一个int作为头指针),最后打印时降序输出即可。代码如下。

/*
功能:根据规则对给定考生成绩进行排序并输出
实现思路:用数组存储每个考生的信息,并且用数组作为静态链表实现排序。
时间复杂度   空间复杂度
*/
import java.io.*;
class Main{public static void main(String[] args) throws IOException{//接收输入BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] arr1 = br.readLine().split(" +");int n = Integer.parseInt(arr1[0]);    //考生总数int l = Integer.parseInt(arr1[1]);    //最低录取分数线int h = Integer.parseInt(arr1[2]);    //优秀录取线//在线排序int[][] a = new int[n][6];    //数组每一行代表一个考生,存储考号、德分、才分、总分、等级、链表序号int m = 0;            //录取总人数String[] b = new String[3];    //接收当前考生的信息int yi = -1;            //已录取学生排序链表中的第一名的角标for(int i=0;i<n;i++){        //在线处理每个考生的信息b = br.readLine().split(" +");    //接收当前考生的信息a[i][0] = Integer.parseInt(b[0]);        //将考生信息转为inta[i][1] = Integer.parseInt(b[1]);a[i][2] = Integer.parseInt(b[2]);a[i] = getGrade(a[i],l,h);    //调用函数填写总分及等级信息,排序地址初始化if(a[i][4]<5){                //若是第一~第四类考生m++;                        //则录取a = getSort(a,i,yi);           //调用函数填写链表地址信息if(a[i][5]==yi)            //判断是否要更新第一名的角标yi = i;}}//打印输出System.out.print(m);    //输出录取总人数if(m==0)    return;        //若是录取人数为0,则直接返回String stu = "";for(int i=yi;;i=a[i][5]){    //按数组静态链表的排序,以成绩降序输出stu = "\n" + a[i][0] + " " +a[i][1] + " " + a[i][2];System.out.print(stu);if(a[i][5]==-1)    //若是链表中录取的最后一名break;            //则跳出循环,停止打印}}private static int[] getGrade(int[] a,int l,int h){//功能:根据数组中学生成绩,填写总分及等级信息 。l是录取线,h是优秀线。a[3] = a[1] + a[2];    //计算总分a[5] = -1;             //排序地址信息初始化if(a[1]<l || a[2]<l){    //若德才有一项未达到录取线a[4] = 5;        //第五类考生,不予录取return a;}if(a[1]>=h && a[2]>=h){    //若德才均优秀a[4] = 1;        //第一类考生return a;}if(a[1]>=h){        //若德分优秀而才分不优秀a[4] = 2;        //第二类考生return a;}    if(a[1]>=a[2]){    //若德分不优秀,但德分≥才分a[4] = 3;        //第三类考生return a;}a[4] = 4;            //其它考生为第四类考生return a;}private static int[][] getSort(int[][] a,int t,int yi){//功能:对数组中指定学生的成绩(以数组静态链表方式)排序并返回数组//参数 a[][] 学生信息数组 ;t 待排序学生角标 ;yi 已排序的录取学生链表中第一名学生角标if(yi==-1)                    //如果链表中还没有学生return a;                   //则以待排序学生作为第一名,直接返回if(gradeCompare(a[t],a[yi])){        //如果待排序的学生是新的第一名a[t][5] = yi;                //待排序学生链接指向原先的第一名return a;}for(int i=yi,j=i;;i=a[i][5]){      //若链表中已经有至少一名学生,则正常进行排序if(gradeCompare(a[i],a[t])){    //若待排序学生成绩<当前对比学生成绩j=i;                            //用j记住当前对比学生角标if(a[i][5]==-1){                //若当前对比学生已经是最后一名a[i][5] = t;                    //将待排序学生插入到链表结尾break;                          //排序完毕,退出循环}}else{                          //若待排序学生成绩>当前对比学生成绩a[j][5] = t;                    //上一名的学生链接到待排序学生a[t][5] = i;                    //待排序学生链接到当前对比学生break;                            //排序完毕,退出循环}}  return a;}private static boolean gradeCompare(int[] a,int[] b){//功能:比较两个学生成绩,学生a是否排名比学生b更靠前if(a[4]<b[4])      //若a比b等级更高return true;if(a[4]>b[4])      //若a比b等级更低return false;//若ab等级相同if(a[3]>b[3])      //若总分a>breturn true;if(a[3]<b[3])      //若总分a<breturn false;//若ab总分相同if(a[1]>b[1])      //若德分a>breturn true;if(a[1]<b[1])      //若德分a<breturn false;//若ab德分相等   return (a[0]<b[0])?true:false;    //则按考号升序排序}
}

有三个测试点超时,考虑到有可能是我自己写的排序算法太慢导致超时,于是我就又写了一个算法。

解法二 

在接收学生信息时只存储不排序,打印时调用java的排序算法,在Arrays.sort()函数中传入一个Comparator匿名内部类(以便自定义排序规则)作为参数,实现排序,之后再降序打印输出。这个解法的一个缺点是要对包括未录取考生在内的所有考生进行排序,而解法一只对录取考生排序。解法二的测试结果仍然是有三个测试点超时。代码如下。

/*
功能:根据规则对给定考生成绩进行排序并输出
实现思路:用数组存储每个考生的信息,并在Arrays.sort()中传入一个Comparator匿名内部类作为参数,以实现排序。
时间复杂度   空间复杂度
*/
import java.io.*;
import java.util.*;
class Main{public static void main(String[] args) throws IOException{//接收输入BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] arr1 = br.readLine().split(" +");int n = Integer.parseInt(arr1[0]);    //考生总数int l = Integer.parseInt(arr1[1]);    //最低录取分数线int h = Integer.parseInt(arr1[2]);    //优秀录取线//逐个接收考生信息Integer[][] a = new Integer[n][5];    //数组每一行代表一个考生,存储考号、德分、才分、总分、等级int m = 0;            //录取总人数String[] b = new String[3];    //接收当前考生的信息for(int i=0;i<n;i++){        //在线处理每个考生的信息b = br.readLine().split(" +");    //接收当前考生的信息for(int j=0;j<3;j++)a[i][j] = Integer.parseInt(b[j]);        //将考生信息转为int    a[i] = getGrade2(a[i],l,h);    //调用函数填写总分及等级信息if(a[i][4]<5){                //若是第一~第四类考生m++;                        //则录取}}//打印输出System.out.print(m);    //输出录取总人数if(m==0)    return;        //若是录取人数为0,则直接返回//调用java提供的数组排序Arrays.sort(a, new Comparator<Integer[]>() {    //new一个Comparator匿名内部类,重写compare方法public int compare(Integer[] b, Integer[] a) {if(a[4]<b[4])      //若a比b等级更高return 1;if(a[4]>b[4])      //若a比b等级更低return -1;//若ab等级相同if(a[3]>b[3])      //若总分a>breturn 1;if(a[3]<b[3])      //若总分a<breturn -1;//若ab总分相同if(a[1]>b[1])      //若德分a>breturn 1;if(a[1]<b[1])      //若德分a<breturn -1;//若ab德分相等   return (a[0]<b[0])?1:-1;    //则按考号升序排序}});//降序输出学生信息String stu = "";for(int i=0;i<m;i++){stu = "\n" + a[i][0] + " " +a[i][1] + " " + a[i][2];System.out.print(stu);}             }private static Integer[] getGrade2(Integer[] a,int l,int h){//功能:根据数组中学生成绩,填写总分及等级信息 。l是录取线,h是优秀线。a[3] = a[1] + a[2];    //计算总分if(a[1]<l || a[2]<l){    //若德才有一项未达到录取线a[4] = 5;        //第五类考生,不予录取return a;}if(a[1]>=h && a[2]>=h){    //若德才均优秀a[4] = 1;        //第一类考生return a;}if(a[1]>=h){        //若德分优秀而才分不优秀a[4] = 2;        //第二类考生return a;}    if(a[1]>=a[2]){    //若德分不优秀,但德分≥才分a[4] = 3;        //第三类考生return a;}a[4] = 4;            //其它考生为第四类考生return a;}
}    

解法三 

既然用java自带的排序算法也不行,那索性还是自己用数组做静态链表的排序吧。考虑到解法一中每个考生排序都要从第一类第一名开始比较,比较耗时,因此我又改进了一下,给四个类别分别设置一个本类别第一名的int角标作为指针。这样,每个考生在排序时只需从所属类别的第一名开始比较即可。此外,这个解法中我还把一些工具函数优化了一下。遗憾的是,测试结果仍然是三个点通过、三个点超时。

/*
功能:根据规则对给定考生成绩进行排序并输出
实现思路:用数组存储每个考生的信息,并且用数组作为静态链表实现排序。
时间复杂度   空间复杂度
*/
import java.io.*;
class Main{public static void main(String[] args) throws IOException{//接收基本信息输入BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] arr1 = br.readLine().split(" +");int n = Integer.parseInt(arr1[0]);    //考生总数int l = Integer.parseInt(arr1[1]);    //最低录取分数线int h = Integer.parseInt(arr1[2]);    //优秀录取线//数组初始化int[][] a = new int[n][6];    //数组每一行代表一个考生,存储考号、德分、才分、总分、等级、链表序号int m = 0;            //录取总人数String[] b = new String[3];    //接收当前考生的信息Integer yi[] = new Integer[4];  //已录取学生排序链表中第一类至第四类的第一名的角标for(int i=0;i<4;i++){           //数组初始化为-1yi[i] = -1;}//在线处理 接收每个学生信息并排序存入数组中for(int i=0,temp=-1;i<n;i++){        //在线处理每个考生的信息b = br.readLine().split(" +");    //接收当前考生的信息a[i][0] = Integer.parseInt(b[0]);        //将考生信息转为inta[i][1] = Integer.parseInt(b[1]);a[i][2] = Integer.parseInt(b[2]);a[i] = getGrade(a[i],l,h);    //调用函数填写总分及等级信息,排序地址初始化if(a[i][4]!=5){                //若是第一~第四类考生m++;                        //则录取temp =a[i][4]-1;     //当前学生所属类别,从0开始计数,yi[temp]是所属类别第一名的角标a = getSort(a,i,yi[temp]);           //调用函数填写链表地址信息if(a[i][5]==yi[temp])            //判断是否要更新该生所属类别第一名的角标yi[temp] = i;}}//打印输出System.out.print(m);    //输出录取总人数if(m==0)    return;        //若是录取人数为0,则直接返回String stu = "";for(int j=0;j<4;j++){       //遍历四个学生类别if(yi[j]==-1)               //若当前类别没有学生continue;               //就继续下一个类别for(int i=yi[j];;i=a[i][5]){    //按数组静态链表的排序,以成绩降序输出stu = "\n" + a[i][0] + " " +a[i][1] + " " + a[i][2];System.out.print(stu);if(a[i][5]==-1)    //若是链表中录取的最后一名break;            //则跳出循环,停止本类别的打印}}   }private static int[] getGrade(int[] a,int l,int h){//功能:根据数组中学生成绩,填写总分及等级信息 。l是录取线,h是优秀线。if(a[1]<l || a[2]<l){    //若德才有一项未达到录取线a[4] = 5;        //第五类考生,不予录取return a;}a[5] = -1;             //对录取学生,排序地址信息初始化a[3] = a[1] + a[2];     //对录取学生,计算德才总分if(a[1]>=h){    //若德分优秀a[4] = (a[2]>=h)?1:2;   //若才分也优秀,则为第一类,否则为第二类return a;}a[4] = (a[1]>=a[2])?3:4;    //若德分不优秀,但德分≥才分,则为第三类,否则其它考生为第四类return a;}private static int[][] getSort(int[][] a,int t,int yi){//功能:对数组中指定学生的成绩(以数组静态链表方式)排序并返回数组//参数 a[][] 学生信息数组 ;t 待排序学生角标 ;yi 待排序学生所属类别的第一名学生角标if(yi==-1)                    //如果当前学生所属类别中还没有学生return a;                   //则以待排序学生作为第一名,直接返回if(gradeCompare(a[t],a[yi])){        //如果待排序的学生是新的第一名a[t][5] = yi;                //待排序学生链接指向原先的第一名return a;}for(int i=yi,j=i;;i=a[i][5]){      //若链表中已经有至少一名学生,则正常进行排序if(gradeCompare(a[i],a[t])){    //若待排序学生成绩<当前对比学生成绩j=i;                            //用j记住当前对比学生角标if(a[i][5]==-1){                //若当前对比学生已经是最后一名a[i][5] = t;                    //将待排序学生插入到链表结尾break;                          //排序完毕,退出循环}}else{                          //若待排序学生成绩>当前对比学生成绩a[j][5] = t;                    //上一名的学生链接到待排序学生(此时j是链表中上一名学生的角标)a[t][5] = i;                    //待排序学生链接到当前对比学生break;                            //排序完毕,退出循环}}  return a;}private static boolean gradeCompare(int[] a,int[] b){//功能:比较两个等级相等的学生成绩,学生a是否排名比学生b更靠前if(a[3]!=b[3])        //若总分不相等return (a[3]>b[3]);         //则返回总分比较结果if(a[1]!=b[1])              //若德分不相等return (a[1]>b[1]);         //则返回德分比较结果return (a[0]<b[0]);              //最后按考号升序排序}
}

结语

以上用java的三种解法都会超时,难道这道题必须用C语言才能不超时吗?也许可以根据考生成绩生成一个唯一的序号,再利用这个序号进行数组的快速排序?等试验了再回来更新吧。

这篇关于PAT(Basic Level) Practice(中文) 1015德才论的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/3013

相关文章

Java下载文件中文文件名乱码的解决方案(文件名包含很多%)

《Java下载文件中文文件名乱码的解决方案(文件名包含很多%)》Java下载文件时,文件名中文乱码问题通常是由于编码不正确导致的,使用`URLEncoder.encode(filepath,UTF-8... 目录Java下载文件中文文件名乱码问题一般情况下,大家都是这样为了解决这个问题最终解决总结Java下

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

vscode中文乱码问题,注释,终端,调试乱码一劳永逸版

忘记咋回事突然出现了乱码问题,很多方法都试了,注释乱码解决了,终端又乱码,调试窗口也乱码,最后经过本人不懈努力,终于全部解决了,现在分享给大家我的方法。 乱码的原因是各个地方用的编码格式不统一,所以把他们设成统一的utf8. 1.电脑的编码格式 开始-设置-时间和语言-语言和区域 管理语言设置-更改系统区域设置-勾选Bata版:使用utf8-确定-然后按指示重启 2.vscode

解决Office Word不能切换中文输入

我们在使用WORD的时可能会经常碰到WORD中无法输入中文的情况。因为,虽然我们安装了搜狗输入法,但是到我们在WORD中使用搜狗的输入法的切换中英文的按键的时候会发现根本没有效果,无法将输入法切换成中文的。下面我就介绍一下如何在WORD中把搜狗输入法切换到中文。

sqlite不支持中文排序,采用java排序

方式一 不支持含有重复字段进行排序 /*** sqlite不支持中文排序,改用java排序* 根据指定的对象属性字段,排序对象集合,顺序* @param list* @param field* @return*/public static List sortListByField(List<?> list,String field){List temp = new ArrayList(

彻底解决win10系统Tomcat10控制台输出中文乱码

彻底解决Tomcat10控制台输出中文乱码 首先乱码问题的原因通俗的讲就是读的编码格式和写的解码格式不一致,比如最常见的两种中文编码UTF-8和GBK,UTF-8一个汉字占三个字节,GBK一个汉字占两个字节,所以当编码与解码格式不一致时,输出端当然无法识别这是啥,所以只能以乱码代替。 值得一提的是GBK不是国家标准编码,常用的国标有两,一个是GB2312,一个是GB18030 GB1

matplotlib中文乱码问题

在使用Matplotlib进行数据可视化的过程中,经常会遇到中文乱码的问题。显示乱码是由于编码问题导致的,而matplotlib 默认使用ASCII 编码,但是当使用pyplot时,是支持unicode编码的,只是默认字体是英文字体,导致中文无法正常显示,所以显示中文乱码。 文本使用系统默认字体、手动指定字体、使用字体管理器来解决。 一、系统默认字体(全局设置字体) 在Matplotlib中

Java实现Smartcn中文分词

新建一个Maven项目,修改pom.xml文件内容:注意版本的不同; <!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-smartcn --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers

MiniCPM-V: A GPT-4V Level MLLM on Your Phone

MiniCPM-V: A GPT-4V Level MLLM on Your Phone 研究背景和动机 现有的MLLM通常需要大量的参数和计算资源,限制了其在实际应用中的范围。大部分MLLM需要部署在高性能云服务器上,这种高成本和高能耗的特点,阻碍了其在移动设备、离线和隐私保护场景中的应用。 文章主要贡献: 提出了MiniCPM-V系列模型,能在移动端设备上部署的MLLM。 性能优越: