答疑
有 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 ≤ n ≤ 1000 , 1 ≤ s i ≤ 60000 , 1 ≤ a i ≤ 1 0 6 , e i ∈ 10000 , 20000 , 30000 1 ≤ n ≤ 1000,1 ≤ s_i ≤ 60000,1 ≤ a_i ≤ 10^6, e_i ∈ {10000, 20000, 30000} 1≤n≤1000,1≤si≤60000,1≤ai≤106,ei∈10000,20000,30000,即 e i e_i ei一定是 10000 、 20000 、 30000 10000、20000、30000 10000、20000、30000之一。
输出描述
输出一个整数,表示同学们在课程群里面发消息的时刻之和最小是多少。
输入输出样例
示例
输入
3
10000 10000 10000
20000 50000 20000
30000 20000 30000
输出
280000
思路
- 贪心法
- 由于题目有关时间先后顺序,所以关键问题是排序
- 读题可知, s i , a i s_i,a_i si,ai 可以合成一个时间段,即一个同学发消息前的时间段, e i e_i ei 则作为一个单独的时间段,即一个同学发完消息之后的时间段
怎么排序呢?
- 要使所有发消息时刻之和最小,首先应该满足一个同学花的所有时间(发消息前后的时间)最小,即时间总和应该从小到大排序
- 其次,如果两个同学所花的总时间一样的话,那么发消息前的时间小的应该先问,即发消息前的时间从小到大排序
- 再次,如果满足总时间一样并且发消息前的时间也一样的话,那么发消息后的时间越小越好,即发消息后的时间从小到大排序
- 总之,所花时间越少越好
排序问题解决之后,那么问题就基本解决了
- 注意数据范围,本题使用 int 型小了,应该使用long long
代码如下
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
using namespace std;
vector<pair<int, int>> a;//存储一个学生所花时间
int n;//学生人数
//核心:排序
bool cmp(const pair<int, int>& a, const pair<int, int>& b) {
if (a.first + a.second == b.first + b.second) {
if (a.first == b.first) return a.second < b.second;
return a.first < b.first;
} else {
return a.first + a.second < b.first + b.second;
}
}
void init() {
scanf("%d", &n);
a.resize(n);
int r = 0, s = 0, t = 0;
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &r, &s, &t);
a[i] = make_pair(r + s, t);
}
sort(a.begin(), a.end(), cmp);
}
void solve() {
ll min_time = a[0].first;
ll cur_time = a[0].first;
for (int i = 1; i < n; i++) {
cur_time += (ll)(a[i].first + a[i - 1].second);
min_time += cur_time;
}
printf("%lld\n", min_time);
}
int main(void) {
init();
solve();
return 0;
}