蓝桥杯真题精讲之一、二
本节实验主要是融汇贯穿前面我们学习过的知识点,通过 4 道蓝桥杯真题进行实战讲解,带领大家学以致用。
蓝桥杯真题精讲之一
2020 年蓝桥杯国赛真题–答疑
题意:
有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。
老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下:
首先进入办公室,编号为 i的同学需要 si 毫秒的时间。
然后同学问问题老师解答,编号为 i 的同学需要 ai 毫秒的时间。
答疑完成后,同学很高兴,会在课程群里面发一条消息,需要的时间可 以忽略。
最后同学收拾东西离开办公室,需要 ei 毫秒的时间。一般需要 10 秒、20 秒或 30 秒,即 ei 取值为 1000,20000 或 30000。
一位同学离开办公室后,紧接着下一位同学就可以进入办公室了。
答疑从 0 时刻开始。老师想合理的安排答疑的顺序,使得同学们在课程群 里面发消息的时刻之和最小。
输入输出:
输入描述:
输入第一行包含一个整数 n,表示同学的数量。
接下来 n 行,描述每位同学的时间。其中第 i 行包含三个整数 si, ai, ei,意义如上所述。
其中有 ,1≤n≤1000,1≤si≤60000,1≤ai≤106,ei∈10000,20000,30000。即 ei 一定是 10000、20000、30000之一。
输入样例:
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