分析:我们采用贪心做法,优先吃过期时间早的。
证明:考虑贪心解和最优解
如果最优解和贪心解不一样,找到第一天不同的点进行比对。
假设贪心解第\(k\)天吃的是\(a_{i}\)苹果,\(k + 1\)天吃的是\(a_{j}\)苹果,而最优解第\(k\)天吃的是\(a_{j}\)苹果,第\(k + 1\)天吃的是\(a_{i}\)苹果。
把最优解第\(k\)天吃的苹果换成\(a_{i}\),只要证明出来方案不会变差,说明贪心解也是一个最优解。
由于贪心解优先吃过期时间早的,那么\(t_{i} <= t_{j}\)

分情况讨论:
情况1:如果最优解中\(a_{i}\)和\(a_{j}\)都有吃,在最优解里面是先吃\(a_{j}\),再吃\(a_{i}\),\(t_{i} <= t_{j}\),交换成贪心解,查看是否会过期,
第一天,先吃\(a_{i}\),由于交换前的最优解里面后吃\(a_{i}\)没有过期,那么提前时间吃,贪心解肯定也不会过期,第二天,吃\(a_{j}\),
由于交换前吃\(a_{i}\)不会过期,且\(a_{i}\)的过期时间早于\(a_{j}\),那么换成\(a_{j}\)也不会过期。因此,贪心解得到的结果不会变差,贪心解也是一个最优解。
情况2:在最优解里面,只吃了\(a_{j}\),没有吃\(a_{i}\),交换,先吃过期时间为\(t_{i}\)的苹果,\(t_{j}\)是在\(t_{i}\)后面过期的,因为交换前吃\(a_{j}\)没有过期,那么交换后吃\(a_{i}\),
因为贪心解里面吃\(a_{i}\)没有过期,那么提前吃\(a_{i}\),在最优解里面也不会过期。
class Solution {
public:
int eatenApples(vector<int>& apples, vector<int>& days) {
typedef pair<int, int> pii;
priority_queue<pii, vector<pii>, greater<pii>> heap;
int res = 0;
int n = apples.size();
for(int i = 0; i <= 40000; ++i)
{
//只将个数大于0的苹果加入到优先队列
if(i < n && apples[i] > 0)
{
heap.push({i + days[i] - 1, apples[i]});
}
//将过期的苹果弹出优先队列
while(heap.size() && heap.top().first < i) heap.pop();
if(heap.empty()) continue;
++res;
//存在过期时间大于当前时间的苹果
auto t = heap.top();
heap.pop();
if(--t.second > 0)
heap.push(t);
}
return res;
}
};
浙公网安备 33010602011771号