描述
在农场里,农民们有一群牛,每头牛的售价和饲养成本不同。农民们将每头牛的利润记录在profits数组中,饲养成本记录在costs数组中。现在农民们想要知道,如果他们只有初始资本w,并且最多只能饲养k头牛,那么他们最终能获得的最大利润是多少。请你编写一个程序,帮助农民们设计完成最多k头牛的饲养计划,以最大化最终利润,并输出最终可获得的最多利润(输出不包括初始资本)。 答案保证在 32 位有符号整数范围内。
示例1
输入:2,0,[2000,3000,4000],[0,1000,1000]
返回值:6000
说明: 由于你的初始资本为 0,你仅可以从 0 号牛开始饲养。 在完成后,你将获得 2000 的利润,你的总资本将变为 2000。 此时你可以选择开始饲养 1 号或 2 号牛。 由于你最多可以选择两头牛,所以你需要饲养 2 号牛以获得最大的利润。 因此,输出最后最大化的利润,为 0 + 2000 + 4000 = 6000。
知识点
贪心
解题思路
使用优先队列来存储一个数组,其中cow[0]表示利润,cow[1]表示饲养成本,利润最大的牛排在队列的前面。
我们将所有牛的利润加入优先队列。由于优先队列是一个最大堆,默认情况下队首元素是利润最大的牛。
然后,我们通过遍历k次的循环来选择饲养k头牛。在每次循环中,如果队列为空或者资本不足以饲养当前利润最大的牛,则将该牛放入到暂存队列中。
否则,我们从队列中取出利润最大的牛,更新可用资本w并加上该牛的利润,将暂存队列中支付不起的牛又放回队列中,然后进入下一次循环。
最终,返回更新后的可用资本w减去成本即可得到最终可获得的最大利润。
Java题解
import java.util.*;
public class Solution {
public int findMaximizedProfits (int k, int w, int[] profits, int[] costs) {
// write code here
int n = profits.length;
int baseW = w; //初始成本
// 创建一个优先队列,用于按照利润将牛排序
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> (b[0] - a[0]));
for (int i = 0; i < n; i++) {
pq.offer(new int[] {profits[i], costs[i]});
}
for (int i = 0; i < k; i++) {
// 创建一个临时队列,用于存储可饲养的牛
PriorityQueue<int[]> tempPq = new PriorityQueue<>((a, b) -> (b[0] - a[0]));
// 将支付不起的牛放进tempPq
while (!pq.isEmpty() && w < pq.peek()[1]) {
int[] cow = pq.poll();
tempPq.offer(cow);
}
// 如果没有可饲养的牛,则结束循环
if (pq.isEmpty()) {
break;
} else {
int[] cow = pq.poll();
w += cow[0];
}
// 将临时队列中的牛重新放回优先队列
while (!tempPq.isEmpty()) {
pq.offer(tempPq.poll());
}
}
return w - baseW;
}
}