题目描述
小林养了一只母鸡,一连 n 天,每天都可以生下若干个鸡蛋。在第 i 天,母鸡会生下 eggs[i] 个鸡蛋,这些鸡蛋将会在days[i] 天后(也就是说,第 i + days[i] 天时)腐烂,变得无法食用。也可能有那么几天,母鸡不会生下新的鸡蛋,此时用 eggs[i] = 0 且 days[i] = 0 表示。你打算每天最多吃一个鸡蛋来保证营养均衡。注意,你可以在这 n 天之后继续吃鸡蛋。给你两个长度为 n 的整数数组 eggs 和 days ,返回你可以吃掉的鸡蛋的最大数目。
输入格式
第一行一个整数n
第二行输入n个整数(空格分开),代表每一天母鸡下蛋数
第三行输入n个整数(空格分开),代表每一天鸡蛋的保质期
输出格式
一个整数,你可以吃掉的鸡蛋的最大数目。
输入输出样例
输入 #1
5
1 2 3 5 2
3 2 1 4 2
输出 #1
7
输入 #2
6
3 0 0 0 0 2
3 0 0 0 0 2
输出 #2
5
说明/提示
对于样例一:
第一天,你吃掉第一天生下的鸡蛋。
第二天,你吃掉一个第二天生下的鸡蛋。
第三天,你吃掉一个第二天生下的鸡蛋。过了这一天,第三天生下的鸡蛋就已经腐烂了。
第四天到第七天,你吃的都是第四天生下的鸡蛋。
对于样例二:
第一天到第三天,你吃的都是第一天生下的鸡蛋。
第四天和第五天不吃鸡蛋。
第六天和第七天,你吃的都是第六天生下的鸡蛋。
1 <= n <= 20000 0 <= eggs[i], days[i] <= 20000
解题思路:
利用优先队列对新加入的鸡蛋进行排序(保质期由短到长),模拟每一天的生蛋弃蛋吃蛋过程。
在前n天里有生蛋的加入优先队列中;检查优先队列中过保质期的蛋舍弃掉;再将保质期最短但未过期的蛋吃掉一个。
最后统计得到吃鸡蛋数。
代码如下:
#include <iostream>
#include <queue>
using namespace std;
const int N = 20010;
int s[N], t[N];struct EGG {int num;int e;friend bool operator < (const EGG &a, const EGG &b) {return a.e > b.e;}
};int ans = 0;
int main() {int n;cin >> n;for (int i = 1; i <= n; i++)cin >> s[i];for (int i = 1; i <= n; i++) {cin >> t[i];if (s[i] > t[i])s[i] = t[i];//鸡蛋有2个,保质期才1天,那2个鸡蛋最多吃一个,所以我们可以认为这天鸡蛋只有一个。}priority_queue<EGG>q;for (int i = 1; i <= n || !q.empty(); i++) {if (i <= n)//因为n天后,我们还可以吃鸡蛋,所以加这个条件{if (s[i] != 0) {EGG egg;egg.num = s[i];egg.e = i + t[i];//假如今天是第2天,下了一个保质期2天的蛋,那它在第4天腐烂(吃不了),所以为i+t[i]q.push(egg);}}while (!q.empty()) {EGG badegg = q.top();if (badegg.e <= i) //保质期过了,将腐烂的出队{q.pop();} elsebreak;}if (!q.empty()) {EGG oneegg;oneegg = q.top();oneegg.num--;if (oneegg.num == 0) {q.pop();}
// else {
// q.pop();
// q.push(oneegg);
// }ans++;}}cout << ans << endl;return 0;
}