【洛谷 P8732】[蓝桥杯 2020 国 ABC] 答疑 题解(向量+结构体排序+贪心算法)

[蓝桥杯 2020 国 ABC] 答疑

题目描述

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

一位同学答疑的过程如下:

  1. 首先进入办公室,编号为 i i i 的同学需要 s i s_{i} si 毫秒的时间。

  2. 然后同学问问题老师解答,编号为 i i i 的同学需要 a i a_{i} ai 毫秒的时间。

  3. 答疑完成后,同学很高兴,会在课程群里面发一条消息,需要的时间可以忽略。

  4. 最后同学收拾东西离开办公室,需要 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 1n20

对于 60 % 60 \% 60% 的评测用例, 1 ≤ n ≤ 200 1 \leq n \leq 200 1n200

对于所有评测用例, 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 1n1000,1si60000,1ai1000000, 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 100002000030000 之一。

蓝桥杯 2020 年国赛 A 组 H 题(B 组 H 题, C 组 J 题)。


思路

假设有两个同学 i i i j j j,在某个答疑顺序中, i i i j j j之前。现在考虑将这两位同学的顺序交换,看看这对总的发消息时间有什么影响。

在交换前,同学 i i i j j j的发消息时间分别为:

  • i i i的发消息时间: s a i sa_i sai
  • j j j的发消息时间: s a i + e i + s a j sa_i + e_i + sa_j sai+ei+saj

所以,交换前的总发消息时间为: s a i + s a i + e i + s a j = 2 s a i + e i + s a j sa_i + sa_i + e_i + sa_j = 2sa_i + e_i + sa_j sai+sai+ei+saj=2sai+ei+saj

在交换后,同学 i i i j j j的发消息时间分别为:

  • j j j的发消息时间: s a j sa_j saj
  • i i i的发消息时间: s a j + e j + s a i sa_j + e_j + sa_i saj+ej+sai

所以,交换后的总发消息时间为: s a j + s a j + e j + s a i = 2 s a j + e j + s a i sa_j + sa_j + e_j + sa_i = 2sa_j + e_j + sa_i saj+saj+ej+sai=2saj+ej+sai

如果 s a i + e i > s a j + e j sa_i + e_i > sa_j + e_j sai+ei>saj+ej,那么交换后的总发消息时间会小于交换前的总发消息时间。

贪心策略:选择 s a + e sa + e sa+e最小的同学先进行答疑可以最小化同学们在课程群里发消息的时刻之和。

首先,定义一个结构体S,其中sa代表同学进入办公室和提问所需的总时间,e代表同学离开办公室所需的时间。

接着,从输入中读取同学的数量n,并对每个同学的进入办公室时间s、提问时间a和离开办公室时间e进行读取。将{s + a, e}作为一个S类型的对象添加到向量v1中。

然后,调用sort函数,对向量v1中的对象按照sa + e的值进行升序排序。

之后,初始化答疑开始的时间t和最小消息时刻之和ans为0。遍历向量v1中的每个对象,每次循环都将当前同学的sa值加到t上,并将结果加到ans上,然后再将当前同学的e值加到t上。这样就得到了所有同学在课程群里发消息的时刻之和。

最后,输出结果ans


AC代码

#include <algorithm>
#include <cmath>
#include <iostream>
#include <vector>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;

const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;

struct S {
	int sa, e;
};

int n;
vector<S> v1;

bool cmp(S a, S b) { return a.sa + a.e < b.sa + b.e; }

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i++) {
		int s, a, e;
		cin >> s >> a >> e;
		v1.push_back({s + a, e});
	}
	sort(v1.begin(), v1.end(), cmp);
	ll ans = 0;
	ll t = 0;
	for (const auto i : v1) {
		ans += t + i.sa;
		// cout << t + i.sa << " ";
		t += i.sa + i.e;
		// cout << t << endl;
	}
	cout << ans << "\n";
	return 0;
}


  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值