哈喽大家好,我是保护小周ღ,本期为大家带来的是博主在牛客网上遇到的一道笔试题,题目不难,但是有点复杂(博主太菜了),博主在做题的过程中使用到了,结构体,动态内存开辟,数据排序,相关知识,包括写着写着被迫使用goto语句,还是值得学习一下的,有没有朋友有其他的解法,欢迎留言啊~
目录
小v今年有n门课,每门都有考试,为了拿到奖学金,小v必须让自己的平均成绩至少为avg。每门课由平时成绩和考试成绩组成,满分为r。在考试前,小v他已经知道每门课的平时成绩为ai ,假设付出的时间与获得的分数成正比,若想让这门课的考试成绩多拿一分的话,小v要花bi 的时间复习,不复习的话当然就是0分。同时我们显然可以发现复习得再多也不会拿到超过满分的分数。问小v为了拿到奖学金,至少要花多少时间复习?
第一行三个整数n,r,avg(1 <= n <= 105,1 <= r <= 109,1 <= avg <= 106),接下来n行,每行两个整数ai和bi,(0 <= ai <= 106,1 <= bi <= 106) 注意:本题含有多组案例输入。
每个用例对应一行输出答案。
输入:
5 10 9 0 5 9 1 8 1 0 1 9 100 3 5 3 2 1 4 100 3 3
输出:
43 0
说明:
示例1有两组测试用例。 对于第2组测试用例,小v的平时成绩的平均成绩为(2+4+3)/3=3分,已经达到拿奖学金的最低要求,所以可以不用复习。
题目要求使用多组输入,所以我们利用while()循环和scanf()函数的返回值,实现多组输入。
第一次输入,n , r ,avg ;
然后我们是不是应该定义一个数组,来记录小V同学的每门课的平时成绩,和如果想要这这些课的成绩提升一分,需要花多少时间复习。这两个种数据。
定义什么?结构体类型的数组,因为同一门课的ai 和 bi 是有联系的,用结构体来描述,再适合不过。
- typedef struct student
- {
- int ai;//每门课的平时成绩
- int bi;//该门功课如果要涨分要花的时间
- }student;
博主这个名字取得不太好,但是使用还是没有问题滴。
小V有几门科目,咱们就开辟多大的空间,存储每一门的平均分数,和对应复习涨分所需要的时间
- student* xiaoV = (student*)malloc(sizeof(student) * n);
- if (xiaoV == NULL)//如果开辟失败就没必要继续了
- {
- perror("malloc");//报个错
- exit(-1);
- }
第二轮循环输入 每门科目的 ai 和 bi ,此时呢,我们还应该记录一下这些科目的平时成绩之和。
假如: 我们光靠平时成绩的平均分就>=avg,拿到奖学金,就不需要复习了。打印0即可。
- int sum = 0;//统计小V同学各科的平时成绩和
- for (int i = 0; i < n; ++i)
- {
- scanf("%d %d", &xiaoV[i].ai, &xiaoV[i].bi);
- sum += xiaoV[i].ai;
- }
- //如果小V同学的各科平时成绩就可以达到拿奖学金的程度。那就不用复习了
- if (sum / n >= avg)
- printf("0\n");
否则:那就要复习了,题目要求:至少要花多少时间复习?
所以,我们复习啊,必须要从涨分容易的科目开始,花的时间少,还能涨分,那我们优先要先找到那些涨分代价小的复习,然后记录一下复习花的时间,每涨一分,咱们就判断一下是否达到拿奖学金的程度,如果可以拿到奖学金,咱们就中止复习操作,然后输出花的时间即可。如果没有拿到,咱们就继续复习,涨分,判断,然后等该门课复习至满分后,继续复习下一门涨分代价小的复习重复操作。
这个点主要的是找复习代价小的,通过什么判断呢,xiaoV[i].bi,小V需要花多少时间复习该门课涨一分。这个值越小越好啊,博主也没啥别的本事,排序耍的还行,我们直接将xiaoV的所以有科目按照xiaoV[i].bi,让xiaoV[i];从小到大排序,然后遍历,执行我上面说的操作。
大家应该能够理解吧?理解的同学扣波1 ,咱们互动一下。
- #include
- #include
- typedef struct student
- {
- int ai;//每门课的平时成绩
- int bi;//该门功课如果要涨分要花的时间
- }student;
-
- int main()
- {
- int n=0;//多少门功课
- int r=0;//满分
- int avg=0;//拿奖学金的平均分
- while(scanf("%d %d %d",&n,&r,&avg)!=EOF)
- {
- //小V有几门科目,咱们就开辟多大的空间,存储每一门的平均分数,和对应复习涨分所需要的时间
- student *xiaoV=(student*)malloc(sizeof(student)*n);
- if(xiaoV==NULL)//如果开辟失败就没必要继续了
- {
- perror("malloc");//报个错
- exit(-1);
- }
-
- int sum=0;//统计小V同学各科的平时成绩和
- for(int i=0;i
- {
- scanf("%d %d",&xiaoV[i].ai,&xiaoV[i].bi);
- sum+=xiaoV[i].ai;
- }
- //如果小V同学的各科平时成绩就可以达到拿奖学金的程度。那就不用复习了
- if(sum/n>=avg)
- printf("0\n");
- else
- {
- //冒泡排序,使涨分花时间代价小的排在前面,优先处理
- //当然也可以使用qsort()库函数排序
- for(int i=0;i
- {
- for(int j=0;j
-1;++j) - {
- if(xiaoV[j].bi>xiaoV[j+1].bi)//小的放在前面
- {
- student tmp=xiaoV[j];//定义结构体student类型的变量临时存储、交换
- xiaoV[j]=xiaoV[j+1];
- xiaoV[j+1]=tmp;
- }
- }
- }
- long time=0;//记录复习提分所需要的时间、因为输入案例较大所以使用long 型
- for(int i=0;i
//判断某一门科目 - {
- //不会拿到超过满分的分数作为判断该科目能涨多少分的结束条件
- for(int j=xiaoV[i].ai+1; j<=r ;++j)//判断该门科目能涨多少分,并且记录所花的时间代价
- {
- time+=xiaoV[i].bi;//统计该科涨分的时间代价
- ++sum;//花时间复习就涨一分
- if(sum/n>=avg)//每涨一分我们就看看是否达到拿奖学金的最低分数
- {
- printf("%ld\n",time);
- free(xiaoV);//释放掉我们动态开辟的空间
- goto end;//我们使用goto跳转出循环
- }
- }
- }
- }
- end: ; //跳转至多组while循环的末尾,使其可以继续多组输入
- }
- return 0;
- }
goto语句
这里博主使用了goto 语句,关于goto 语句,博主简单讲两下:
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。 从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。 但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过 程。 例如:一次跳出两层或多层循环。 多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。就像博主遇到的情况,已经达到可以拿到奖学金的程度,就没必要复习了。如果break;中止内部循环,实际上,外循环还是会继续运行的,没必要了。
goto语言真正适合的场景如下:
for(...) {
for(...) {
for(...) {
if(disaster)
goto error;
}
} …
}
error: ;
感兴趣的朋友可以用博主的方法,或者是自己的方法做做这道题,优化一下代码。
题目来源于牛客网
题目链接:奖学金_牛客题霸_牛客网 (nowcoder.com)
本期收录于博主的专栏——每日一题,适用于编程初学者,有兴趣的朋友们可以订阅,查看其它“精彩小题”。每日一题_保护小周ღ的博客-CSDN博客
感谢每一个观看本篇文章的朋友,更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★*
如有侵权请联系修改删除!
-
相关阅读:
[含毕业设计论文+PPT+源码等]ssm培训机构管理系统+Java后台管理系统|前后分离VUE
vue考核点示例(仅供参考)
.NET的CancellationTokenSource和ManualResetEvent结合使用
vue:对三种获取更新后的dom的方式进行分析
嵌入式实时操作系统的设计与开发(调度线程学习)
git学习笔记——git pull篇
【Java】认识类和对象
QT 第六天 人脸识别系统
VLAN实验一 VLAN的简单配置
【数据库】Sql Server 2022通过临时表和游标遍历方式逻辑处理获取目标数据
-
原文地址:https://blog.csdn.net/weixin_67603503/article/details/125979489