每日一题——奖学金

简介:  哈喽大家好,我是保护小周ღ,本期为大家带来的是博主在牛客网上遇到的一道笔试题,题目不难,但是有点复杂(博主太菜了),博主在做题的过程中使用到了,结构体,动态内存开辟,数据排序,相关知识,包括写着写着被迫使用goto语句,还是值得学习一下的,有没有朋友有其他的解法,欢迎留言啊~

 image.gif编辑

哈喽大家好,我是保护小周ღ,本期为大家带来的是博主在牛客网上遇到的一道笔试题,题目不难,但是有点复杂(博主太菜了),博主在做题的过程中使用到了,结构体动态内存开辟数据排序,相关知识,包括写着写着被迫使用goto语句,还是值得学习一下的,有没有朋友有其他的解法,欢迎留言啊~

image.gif编辑

目录

博主题目分析:

程序设计:

程序实现:

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) 注意:本题含有多组案例输入。

输出描述:

每个用例对应一行输出答案。

示例1

输入:

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分,已经达到拿奖学金的最低要求,所以可以不用复习。


博主题目分析:

    1. 首先,小V想要拿奖学金,所以他必须保证,他的各科总平时成绩大于等于 avg ,每一门课的满分为 r ,然后 n 代表的是小V的所有学科。
    2. 第一轮输入 n=有多少门课,r=科目的满分是多少, avg=总平均成绩要达到avg,才能获得奖学金。
    3. 第二轮多组输入,输入 ai =该门课的平时成绩, 输入 bi =如果想要这门课的成绩提升一分,需要花多少时间复习。然后输入下一门课的ai 和bi;
    4. 复习得再多也不会拿到超过满分的分数。

    程序设计:

    题目要求使用多组输入,所以我们利用while()循环和scanf()函数的返回值,实现多组输入。

    第一次输入,n , r ,avg ;

    然后我们是不是应该定义一个数组,来记录小V同学的每门课的平时成绩,和如果想要这这些课的成绩提升一分,需要花多少时间复习。这两个种数据。

    定义什么?结构体类型的数组,因为同一门课的ai 和 bi 是有联系的,用结构体来描述,再适合不过。

    typedefstructstudent{
    intai;//每门课的平时成绩intbi;//该门功课如果要涨分要花的时间}student;

    image.gif

    博主这个名字取得不太好,但是使用还是没有问题滴。

    小V有几门科目,咱们就开辟多大的空间,存储每一门的平均分数,和对应复习涨分所需要的时间

    student*xiaoV= (student*)malloc(sizeof(student) *n);
    if (xiaoV==NULL)//如果开辟失败就没必要继续了{
    perror("malloc");//报个错exit(-1);
    }

    image.gif

    第二轮循环输入 每门科目的 ai 和 bi ,此时呢,我们还应该记录一下这些科目的平时成绩之和。

    假如: 我们光靠平时成绩的平均分就>=avg,拿到奖学金,就不需要复习了。打印0即可。

    intsum=0;//统计小V同学各科的平时成绩和for (inti=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");

    image.gif

    否则:那就要复习了,题目要求:至少要花多少时间复习?

    所以,我们复习啊,必须要从涨分容易的科目开始,花的时间少,还能涨分,那我们优先要先找到那些涨分代价小的复习,然后记录一下复习花的时间,每涨一分,咱们就判断一下是否达到拿奖学金的程度,如果可以拿到奖学金,咱们就中止复习操作,然后输出花的时间即可。如果没有拿到,咱们就继续复习,涨分,判断,然后等该门课复习至满分后,继续复习下一门涨分代价小的复习重复操作。

    这个点主要的是找复习代价小的,通过什么判断呢,xiaoV[i].bi,小V需要花多少时间复习该门课涨一分。这个值越小越好啊,博主也没啥别的本事,排序耍的还行,我们直接将xiaoV的所以有科目按照xiaoV[i].bi,让xiaoV[i];从小到大排序,然后遍历,执行我上面说的操作。

    大家应该能够理解吧?理解的同学扣波1 ,咱们互动一下。image.gif编辑


    程序实现:

    #include<stdio.h>#include<stdlib.h>typedefstructstudent{
    intai;//每门课的平时成绩intbi;//该门功课如果要涨分要花的时间}student;
    intmain()
    {
    intn=0;//多少门功课intr=0;//满分intavg=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);
            }
    intsum=0;//统计小V同学各科的平时成绩和for(inti=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");
    else        {
    //冒泡排序,使涨分花时间代价小的排在前面,优先处理//当然也可以使用qsort()库函数排序for(inti=0;i<n;++i)
                {
    for(intj=0;j<n-i-1;++j)
                    {
    if(xiaoV[j].bi>xiaoV[j+1].bi)//小的放在前面                    {
    studenttmp=xiaoV[j];//定义结构体student类型的变量临时存储、交换xiaoV[j]=xiaoV[j+1];
    xiaoV[j+1]=tmp;
                        }
                    }
                }
    longtime=0;//记录复习提分所需要的时间、因为输入案例较大所以使用long 型for(inti=0;i<n;++i)//判断某一门科目            {
    //不会拿到超过满分的分数作为判断该科目能涨多少分的结束条件for(intj=xiaoV[i].ai+1; j<=r ;++j)//判断该门科目能涨多少分,并且记录所花的时间代价                { 
    time+=xiaoV[i].bi;//统计该科涨分的时间代价++sum;//花时间复习就涨一分if(sum/n>=avg)//每涨一分我们就看看是否达到拿奖学金的最低分数                    {
    printf("%ld\n",time); 
    free(xiaoV);//释放掉我们动态开辟的空间gotoend;//我们使用goto跳转出循环                    }
                    }
                }
            }
    end: ; //跳转至多组while循环的末尾,使其可以继续多组输入    }
    return0;
    }

    image.gif


    goto语句

    这里博主使用了goto 语句,关于goto 语句,博主简单讲两下:

    C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。 从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。 但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过 程。 例如:一次跳出两层或多层循环。 多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。就像博主遇到的情况,已经达到可以拿到奖学金的程度,就没必要复习了。如果break;中止内部循环,实际上,外循环还是会继续运行的,没必要了。

    goto语言真正适合的场景如下:

    for(...)  {

         for(...)   {      

                for(...)   {            

                                 if(disaster)  

                                 goto error;      

                }  

         }    …

    }

    error: ;

     


    感兴趣的朋友可以用博主的方法,或者是自己的方法做做这道题,优化一下代码。

    题目来源于牛客网

    image.gif编辑

    题目链接:奖学金_牛客题霸_牛客网 (nowcoder.com)

    本期收录于博主的专栏——每日一题,适用于编程初学者,有兴趣的朋友们可以订阅,查看其它“精彩小题”。每日一题_保护小周ღ的博客-CSDN博客

    感谢每一个观看本篇文章的朋友,更多精彩敬请期待:保护小周ღ  *★,°*:.☆( ̄▽ ̄)/$:*.°★*

    image.gif编辑

     如有侵权请联系修改删除!

    相关文章
    |
    算法
    蓝桥杯算法竞赛第一周题型总结
    蓝桥杯算法竞赛第一周题型总结
    73 0
    |
    4月前
    【洛谷】P1678 烦恼的高考志愿
    洛谷 P1678 烦恼的高考志愿
    44 2
    【洛谷】P1678 烦恼的高考志愿
    |
    机器学习/深度学习 定位技术 数据格式
    【蓝桥杯】每日一题17天冲刺国赛
    【蓝桥杯】每日一题17天冲刺国赛
    598 0
    【蓝桥杯】每日一题17天冲刺国赛
    |
    6月前
    |
    C++
    C++期末考试注意点
    C++期末考试注意点
    22 0
    |
    6月前
    |
    存储
    每日一题——leetcode682.棒球比赛
    每日一题——leetcode682.棒球比赛
    |
    6月前
    |
    内存技术
    |
    存储
    【蓝桥杯冲刺】蓝桥杯12届省赛C++b组真题-填空题
    【蓝桥杯冲刺】蓝桥杯12届省赛C++b组真题-填空题
    101 1
    下一篇
    无影云桌面