0
点赞
收藏
分享

微信扫一扫

【蓝桥杯】答疑

一只1994 2022-02-27 阅读 145

答疑

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} 1n10001si600001ai106ei10000,20000,30000,即 e i e_i ei一定是 10000 、 20000 、 30000 10000、20000、30000 100002000030000之一。

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

输入输出样例
示例
输入

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;
}
举报

相关推荐

0 条评论