蓝桥杯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;
}

浙公网安备 33010602011771号