蓝桥杯书的笔记(四:蓝桥云课完结,C++)


本节实验主要是融汇贯穿前面我们学习过的知识点,通过 4 道蓝桥杯真题进行实战讲解,带领大家学以致用。

蓝桥杯真题精讲之一

2020 年蓝桥杯国赛真题–答疑

题意:

有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。
老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下:

    首先进入办公室,编号为 i的同学需要 si​ 毫秒的时间。
    然后同学问问题老师解答,编号为 i 的同学需要 ai​ 毫秒的时间。
    答疑完成后,同学很高兴,会在课程群里面发一条消息,需要的时间可 以忽略。
    最后同学收拾东西离开办公室,需要 ei​ 毫秒的时间。一般需要 10 秒、20 秒或 30 秒,即 ei​ 取值为 10002000030000。

一位同学离开办公室后,紧接着下一位同学就可以进入办公室了。
答疑从 0 时刻开始。老师想合理的安排答疑的顺序,使得同学们在课程群 里面发消息的时刻之和最小。

输入输出:

输入描述:
输入第一行包含一个整数 n,表示同学的数量。

接下来 n 行,描述每位同学的时间。其中第 i 行包含三个整数 si​, ai​, ei​,意义如上所述。

其中有 ,1≤n≤10001≤si≤600001≤ai≤106,ei∈10000,20000,30000。即 ei​ 一定是 100002000030000之一。

输入样例:
3
10000 10000 10000
20000 50000 20000
30000 20000 30000

输出描述:
输出一个整数,表示同学们在课程群里面发消息的时刻之和最小是多少。

输出样例:
280000

题目解析

本题是一个贪心问题,要想使得所有的时刻之和最小,就要使得每一个时刻尽可能少,根据题目我们可以得到每位同学的时刻=每位同学的等待时间+进门时间+答疑时间。

由于答疑时间是已知的,要使得每位同学的时刻最小,那么就要使得每位同学的等待时间最小。如何使得等待时间最小的呢?

如果这么考虑这道题是做不出来的,我们应该考虑的是使得每位同学等待的时间和最小。

每位同学的时刻 = 每位同学的等待时间 + 进门时间 + 答疑时间
             = 前一位同学的等待时间 + 前一位同学的进门时间 + 前一位同学的答疑时间 + 前一位同学的收拾东西的时间 + 进门时间 + 答疑时间

在这里插入图片描述
使用贪心算法后,我们可以得出结论是,每位同学的等待时间(前一位同学的等待时间 + 前一位同学的进门时间 + 答疑时间 + 前一位同学的收拾东西的时间)最小。

但是如果相同的时候,两者前后关系是什么?

  • 因为是答疑结束后就发消息,而不是出门之后发消息,所以两者存在前后关系,谁先答疑结束谁就先执行。
  • 我们还要进一步考虑,如果进门时间+答疑时间相同,即答疑同时结束,既然答疑同时结束,那么谁先谁后结果是相同的,所以不用继续考虑,到此,贪心策略完整的生成。

即:我们选取最小的进门时间+答疑时间+收拾东西时间之和最小的人在前,且当进门时间 + 答疑时间 + 收拾东西时间的和相同时,选择最小的进门时间 + 答疑时间。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;
int n;

struct Stu
{
   
   
    int inD;
    //进门所需时间

    int answQ;
     //答疑所需时间

    int outD;
    //收拾东西所需时间

    int sum1;
    //贪心准则1=进门时间+答疑时间+收拾东西时间

    int sum2;
    //贪心准则2=进门时间+答疑时间+收拾东西时间
} stu[N];


//贪心准则
bool cmp(Stu st1, Stu st2)
{
   
   
    if(st1.sum1 != st2.sum1)    return st1.sum1 < st2.sum1;
    else return st1.sum2 < st2.sum2;
}

int main()
{
   
   
    //输入数据
    scanf("%d", &n);

    for(int i = 0; i < n; i ++ )
    {
   
   
        scanf("%d%d%d", &stu[i].inD, &stu[i].answQ, &stu[i].outD);

        //标准生成
        stu[i].sum1= stu[i].inD + stu[i].answQ+stu[i].outD;
        stu[i].sum2 =  stu[i].inD + stu[i].answQ;
    }

    //贪心过程及结果计算
    sort(stu, stu + n, cmp);

    long long res = 0, t = 0;

    for(int i = 0; i < n; i ++ )
    {
   
   
        t += stu[i].sum2;

        res += t;

        t += stu[i].outD;

    }

    cout << res << endl;

    return 0;
}

2012 年蓝桥杯省赛真题–鲁卡斯队列

这道题是基于前缀和的模拟题,我们按照要求进行模拟即可。
题意:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

黄金分割数 0.618 与美学有重要的关系。舞台上报幕员所站的位置大约就是舞台宽度的 0.618 处,墙上的画像一般也挂在房间高度的 0.618 处,甚至股票的波动据说也能找到 0.618 的影子....

黄金分割数是个无理数,也就是无法表示为两个整数的比值。0.618 只是它的近似值,其真值可以通过对 5 开方减去 1 再除以 2 来获得,我们取它的一个较精确的近似值:0.618034 。

有趣的是,一些简单的数列中也会包含这个无理数,这很令数学家震惊!
1 3 4 7 11 18 29 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒回顾,半缘君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值