蓝桥杯2021国赛:巧克力 【贪心】

题目描述

小蓝很喜欢吃巧克力,他每天都要吃一块巧克力。

一天小蓝到超市想买一些巧克力。超市的货架上有很多种巧克力,每种巧克力有自己的价格、数量和剩余的保质期天数,小蓝只吃没过保质期的巧克力,请问小蓝最少花多少钱能买到让自己吃 \(x\) 天的巧克力。

输入描述

输入的第一行包含两个整数 \(x,n\),分别表示需要吃巧克力的天数和巧克力的种类数。

接下来 \(n\) 行描述货架上的巧克力,其中第 \(i\) 行包含三个整数\(a_i,b_i,c_i\),表示第\(i\) 种巧克力的单价为 \(a_i\),保质期还剩 \(b_i\) 天(从现在开始的 \(b_i\) 天可以吃),数量为 \(c_i\)

输出描述

输出一个整数表示小蓝的最小花费。如果不存在让小蓝吃 \(x\) 天的购买方案,输出 \(−1\)

评测用例规模与约定

对于 \(30\%\) 的评测用例,\(n,x≤1000\)

对于所有评测用例,\(1≤n,x≤100000,1≤a_i,b_i,c_i≤10^9\)

思路(有参考):

首先直接的思路是对价格升序排序,接下来考虑怎么选择最优的保质期。

若一个巧克力的保值期为\(k\),那么它只能在\([1,k]\)天被吃掉。那么将巧克力放在第\(k\)天吃掉一定是最优策略。在遍历每个巧克力的时候,寻找当前最大的没有巧克力吃的日子\(t\),并将其放在第\(t\)天;如果找不到则忽略。

使用\(set\)存储没有巧克力吃的日期,一旦有巧克力吃则将\(k\)删除,如果当前保质期小于\(set.begin()\),则代表保质期已过。

void solve() {
    int x, res = 0;
    cin >> x >> n;
    for (int i = 1; i <= n; i++) cin >> t[i].a >> t[i].b >> t[i].c;
    sort(t + 1, t + 1 + n);
    set<int> s;
    for (int i = 1; i <= x; i++) s.insert(i);
    for (int i = 1; i <= n; i++) {
        if (s.empty()) break;
        while (s.size() && t[i].c && t[i].b >= *s.begin()) {
            res += t[i].a;
            --t[i].c;
            auto it = s.upper_bound(t[i].b);
            it--;//找到最大的吃巧克力的一天
            s.erase(it);
        }
    }
    if (s.size()) cout << -1 << endl;
    else cout << res << endl;
}
posted @ 2023-02-27 20:00  SxtoxA  阅读(79)  评论(0)    收藏  举报
12 13