本文涉及知识点
C++贪心 临项交换
P8732 [蓝桥杯 2020 国 ABC]
题目描述
有 n n n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。
一位同学答疑的过程如下:
-
首先进入办公室,编号为 i i i 的同学需要 s i s_{i} si 毫秒的时间。
-
然后同学问问题老师解答,编号为 i i i 的同学需要 a i a_{i} ai 毫秒的时间。
-
答疑完成后,同学很高兴,会在课程群里面发一条消息,需要的时间可以忽略。
-
最后同学收拾东西离开办公室,需要 e i e_{i} ei 毫秒的时间。一般需要 10 10 10 秒、 20 20 20 秒或 30 30 30 秒,即 e i e_{i} ei 取值为 10000 10000 10000、 20000 20000 20000 或 30000 30000 30000。
一位同学离开办公室后,紧接着下一位同学就可以进入办公室了。
答疑从 0 0 0 时刻开始。老师想合理的安排答疑的顺序,使得同学们在课程群里面发消息的时刻之和最小。
输入格式
输入第一行包含一个整数 n n n,表示同学的数量。
接下来 n n n 行, 描述每位同学的时间。其中第 i i i 行包含三个整数 s i , a i , e i s_{i}, a_{i}, e_{i} si,ai,ei,意义如上所述。
输出格式
输出一个整数,表示同学们在课程群里面发消息的时刻之和最小是多少。
样例 #1
样例输入 #1
3
10000 10000 10000
20000 50000 20000
30000 20000 30000
样例输出 #1
280000
提示
【样例说明】
按照 1 , 3 , 2 1,3,2 1,3,2 的顺序答疑,发消息的时间分别是 20000 , 80000 , 180000 20000,80000,180000 20000,80000,180000 。
【评测用例规模与约定】
对于 30 % 30 \% 30% 的评测用例, 1 ≤ n ≤ 20 1 \leq n \leq 20 1≤n≤20 。
对于 60 % 60 \% 60% 的评测用例, 1 ≤ n ≤ 200 1 \leq n \leq 200 1≤n≤200 。
对于所有评测用例, 1 ≤ n ≤ 1000 , 1 ≤ s i ≤ 60000 , 1 ≤ a i ≤ 1000000 1 \leq n \leq 1000,1 \leq s_{i} \leq 60000,1 \leq a_{i} \leq 1000000 1≤n≤1000,1≤si≤60000,1≤ai≤1000000, e i ∈ { 10000 , 20000 , 30000 } e_{i} \in\{10000,20000,30000\} ei∈{10000,20000,30000} ,即 e i e_{i} ei 一定是 10000 、 20000 、 30000 10000 、 20000 、 30000 10000、20000、30000 之一。
蓝桥杯 2020 年国赛 A 组 H 题(B 组 H 题, C 组 J 题)。
贪心之临项交换
某个方案,第i个学生后面是第j个学生。令第i个学生四项目操作的时间分别是a,b,0,c;令第j个学生四项操作的时间分别是d,e,0,f。交换i,j,对其他学生无影响,故只考第i个和第j个学生的影响。
交换前:a+b+(a+b+c)+d+e
交换后:d+e+(d +e +f )+a+b
交换后减交换前:x = d+e+f -(a+b+c) 如果x <0,值得交换,即d+e+f < a+b+c。d+e+f小的在前,即升序。
代码
核心代码
cpp
class Solution {
public:
long long MinMS(vector<tuple<int, int, int>>& times) {
sort(times.begin(), times.end(), [&](const tuple<int, int, int>& t1, const tuple<int, int, int>& t2) {
return get<0>(t1) + get<1>(t1) + get<2>(t1) < get<0>(t2) + get<1>(t2) + get<2>(t2);
});
long long ans = 0, cur = 0;
for (const auto& [a, b, c] : times) {
cur += (a + b);
ans += cur;
cur += c;
}
return ans;
}
};
int main() {
//freopen("a.in", "r", stdin);
int n,m;
scanf("%d", &n);
vector<tuple<int,int,int>> times;
for (int i = 0; i < n; i++) {
tuple<int, int, int> t;
int d1, d2, d3;
scanf("%d%d%d", &d1,&d2,&d3);
times.emplace_back(d1, d2, d3);
}
auto res = Solution().MinMS(times);
printf("%lld\n", res);
return 0;
}
单元测试
cpp
TEST_METHOD(TestMethod11)
{
vector<tuple<int, int, int>> times = { {10000, 10000, 10000},{20000 ,50000 ,20000},{30000 ,20000, 30000} };
auto res = Solution().MinMS(times);
AssertEx(280000LL, res);
}
扩展阅读
我想对大家说的话 |
---|
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
失败+反思=成功 成功+反思=成功 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。